]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
for now, turn off FBO if multisampling as their combination is not implemented yet
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
144 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 cvar_t r_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"};
151 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"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 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"};
155 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)"};
156 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)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158
159 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)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 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)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 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)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 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"};
167 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."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177
178 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)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 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"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 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"};
185 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"};
186 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)"};
187
188 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
189 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
190 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
191 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
192
193 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
194 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
195 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
196 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
197 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
198 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
199 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
200
201 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
202 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
210 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
211
212 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"};
213
214 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"};
215
216 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
217
218 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
219
220 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
221 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"};
222
223 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."};
224
225 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)"};
226
227 extern cvar_t v_glslgamma;
228 extern cvar_t v_glslgamma_2d;
229
230 extern qboolean v_flipped_state;
231
232 r_framebufferstate_t r_fb;
233
234 /// shadow volume bsp struct with automatically growing nodes buffer
235 svbsp_t r_svbsp;
236
237 rtexture_t *r_texture_blanknormalmap;
238 rtexture_t *r_texture_white;
239 rtexture_t *r_texture_grey128;
240 rtexture_t *r_texture_black;
241 rtexture_t *r_texture_notexture;
242 rtexture_t *r_texture_whitecube;
243 rtexture_t *r_texture_normalizationcube;
244 rtexture_t *r_texture_fogattenuation;
245 rtexture_t *r_texture_fogheighttexture;
246 rtexture_t *r_texture_gammaramps;
247 unsigned int r_texture_gammaramps_serial;
248 //rtexture_t *r_texture_fogintensity;
249 rtexture_t *r_texture_reflectcube;
250
251 // TODO: hash lookups?
252 typedef struct cubemapinfo_s
253 {
254         char basename[64];
255         rtexture_t *texture;
256 }
257 cubemapinfo_t;
258
259 int r_texture_numcubemaps;
260 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
261
262 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
263 unsigned int r_numqueries;
264 unsigned int r_maxqueries;
265
266 typedef struct r_qwskincache_s
267 {
268         char name[MAX_QPATH];
269         skinframe_t *skinframe;
270 }
271 r_qwskincache_t;
272
273 static r_qwskincache_t *r_qwskincache;
274 static int r_qwskincache_size;
275
276 /// vertex coordinates for a quad that covers the screen exactly
277 extern const float r_screenvertex3f[12];
278 extern const float r_d3dscreenvertex3f[12];
279 const float r_screenvertex3f[12] =
280 {
281         0, 0, 0,
282         1, 0, 0,
283         1, 1, 0,
284         0, 1, 0
285 };
286 const float r_d3dscreenvertex3f[12] =
287 {
288         0, 1, 0,
289         1, 1, 0,
290         1, 0, 0,
291         0, 0, 0
292 };
293
294 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
295 {
296         int i;
297         for (i = 0;i < verts;i++)
298         {
299                 out[0] = in[0] * r;
300                 out[1] = in[1] * g;
301                 out[2] = in[2] * b;
302                 out[3] = in[3];
303                 in += 4;
304                 out += 4;
305         }
306 }
307
308 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
309 {
310         int i;
311         for (i = 0;i < verts;i++)
312         {
313                 out[0] = r;
314                 out[1] = g;
315                 out[2] = b;
316                 out[3] = a;
317                 out += 4;
318         }
319 }
320
321 // FIXME: move this to client?
322 void FOG_clear(void)
323 {
324         if (gamemode == GAME_NEHAHRA)
325         {
326                 Cvar_Set("gl_fogenable", "0");
327                 Cvar_Set("gl_fogdensity", "0.2");
328                 Cvar_Set("gl_fogred", "0.3");
329                 Cvar_Set("gl_foggreen", "0.3");
330                 Cvar_Set("gl_fogblue", "0.3");
331         }
332         r_refdef.fog_density = 0;
333         r_refdef.fog_red = 0;
334         r_refdef.fog_green = 0;
335         r_refdef.fog_blue = 0;
336         r_refdef.fog_alpha = 1;
337         r_refdef.fog_start = 0;
338         r_refdef.fog_end = 16384;
339         r_refdef.fog_height = 1<<30;
340         r_refdef.fog_fadedepth = 128;
341         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
342 }
343
344 static void R_BuildBlankTextures(void)
345 {
346         unsigned char data[4];
347         data[2] = 128; // normal X
348         data[1] = 128; // normal Y
349         data[0] = 255; // normal Z
350         data[3] = 255; // height
351         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352         data[0] = 255;
353         data[1] = 255;
354         data[2] = 255;
355         data[3] = 255;
356         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357         data[0] = 128;
358         data[1] = 128;
359         data[2] = 128;
360         data[3] = 255;
361         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
362         data[0] = 0;
363         data[1] = 0;
364         data[2] = 0;
365         data[3] = 255;
366         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
367 }
368
369 static void R_BuildNoTexture(void)
370 {
371         int x, y;
372         unsigned char pix[16][16][4];
373         // this makes a light grey/dark grey checkerboard texture
374         for (y = 0;y < 16;y++)
375         {
376                 for (x = 0;x < 16;x++)
377                 {
378                         if ((y < 8) ^ (x < 8))
379                         {
380                                 pix[y][x][0] = 128;
381                                 pix[y][x][1] = 128;
382                                 pix[y][x][2] = 128;
383                                 pix[y][x][3] = 255;
384                         }
385                         else
386                         {
387                                 pix[y][x][0] = 64;
388                                 pix[y][x][1] = 64;
389                                 pix[y][x][2] = 64;
390                                 pix[y][x][3] = 255;
391                         }
392                 }
393         }
394         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
395 }
396
397 static void R_BuildWhiteCube(void)
398 {
399         unsigned char data[6*1*1*4];
400         memset(data, 255, sizeof(data));
401         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
402 }
403
404 static void R_BuildNormalizationCube(void)
405 {
406         int x, y, side;
407         vec3_t v;
408         vec_t s, t, intensity;
409 #define NORMSIZE 64
410         unsigned char *data;
411         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
412         for (side = 0;side < 6;side++)
413         {
414                 for (y = 0;y < NORMSIZE;y++)
415                 {
416                         for (x = 0;x < NORMSIZE;x++)
417                         {
418                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
419                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 switch(side)
421                                 {
422                                 default:
423                                 case 0:
424                                         v[0] = 1;
425                                         v[1] = -t;
426                                         v[2] = -s;
427                                         break;
428                                 case 1:
429                                         v[0] = -1;
430                                         v[1] = -t;
431                                         v[2] = s;
432                                         break;
433                                 case 2:
434                                         v[0] = s;
435                                         v[1] = 1;
436                                         v[2] = t;
437                                         break;
438                                 case 3:
439                                         v[0] = s;
440                                         v[1] = -1;
441                                         v[2] = -t;
442                                         break;
443                                 case 4:
444                                         v[0] = s;
445                                         v[1] = -t;
446                                         v[2] = 1;
447                                         break;
448                                 case 5:
449                                         v[0] = -s;
450                                         v[1] = -t;
451                                         v[2] = -1;
452                                         break;
453                                 }
454                                 intensity = 127.0f / sqrt(DotProduct(v, v));
455                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
456                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
457                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
458                                 data[((side*64+y)*64+x)*4+3] = 255;
459                         }
460                 }
461         }
462         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
463         Mem_Free(data);
464 }
465
466 static void R_BuildFogTexture(void)
467 {
468         int x, b;
469 #define FOGWIDTH 256
470         unsigned char data1[FOGWIDTH][4];
471         //unsigned char data2[FOGWIDTH][4];
472         double d, r, alpha;
473
474         r_refdef.fogmasktable_start = r_refdef.fog_start;
475         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
476         r_refdef.fogmasktable_range = r_refdef.fogrange;
477         r_refdef.fogmasktable_density = r_refdef.fog_density;
478
479         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
480         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
481         {
482                 d = (x * r - r_refdef.fogmasktable_start);
483                 if(developer_extra.integer)
484                         Con_DPrintf("%f ", d);
485                 d = max(0, d);
486                 if (r_fog_exp2.integer)
487                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
488                 else
489                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
490                 if(developer_extra.integer)
491                         Con_DPrintf(" : %f ", alpha);
492                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
493                 if(developer_extra.integer)
494                         Con_DPrintf(" = %f\n", alpha);
495                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
496         }
497
498         for (x = 0;x < FOGWIDTH;x++)
499         {
500                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
501                 data1[x][0] = b;
502                 data1[x][1] = b;
503                 data1[x][2] = b;
504                 data1[x][3] = 255;
505                 //data2[x][0] = 255 - b;
506                 //data2[x][1] = 255 - b;
507                 //data2[x][2] = 255 - b;
508                 //data2[x][3] = 255;
509         }
510         if (r_texture_fogattenuation)
511         {
512                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
513                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514         }
515         else
516         {
517                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
518                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
519         }
520 }
521
522 static void R_BuildFogHeightTexture(void)
523 {
524         unsigned char *inpixels;
525         int size;
526         int x;
527         int y;
528         int j;
529         float c[4];
530         float f;
531         inpixels = NULL;
532         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
533         if (r_refdef.fogheighttexturename[0])
534                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
535         if (!inpixels)
536         {
537                 r_refdef.fog_height_tablesize = 0;
538                 if (r_texture_fogheighttexture)
539                         R_FreeTexture(r_texture_fogheighttexture);
540                 r_texture_fogheighttexture = NULL;
541                 if (r_refdef.fog_height_table2d)
542                         Mem_Free(r_refdef.fog_height_table2d);
543                 r_refdef.fog_height_table2d = NULL;
544                 if (r_refdef.fog_height_table1d)
545                         Mem_Free(r_refdef.fog_height_table1d);
546                 r_refdef.fog_height_table1d = NULL;
547                 return;
548         }
549         size = image_width;
550         r_refdef.fog_height_tablesize = size;
551         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
552         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
553         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
554         Mem_Free(inpixels);
555         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
556         // average fog color table accounting for every fog layer between a point
557         // and the camera.  (Note: attenuation is handled separately!)
558         for (y = 0;y < size;y++)
559         {
560                 for (x = 0;x < size;x++)
561                 {
562                         Vector4Clear(c);
563                         f = 0;
564                         if (x < y)
565                         {
566                                 for (j = x;j <= y;j++)
567                                 {
568                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
569                                         f++;
570                                 }
571                         }
572                         else
573                         {
574                                 for (j = x;j >= y;j--)
575                                 {
576                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577                                         f++;
578                                 }
579                         }
580                         f = 1.0f / f;
581                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
582                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
585                 }
586         }
587         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
588 }
589
590 //=======================================================================================================================================================
591
592 static const char *builtinshaderstring =
593 #include "shader_glsl.h"
594 ;
595
596 const char *builtinhlslshaderstring =
597 #include "shader_hlsl.h"
598 ;
599
600 char *glslshaderstring = NULL;
601 char *hlslshaderstring = NULL;
602
603 //=======================================================================================================================================================
604
605 typedef struct shaderpermutationinfo_s
606 {
607         const char *pretext;
608         const char *name;
609 }
610 shaderpermutationinfo_t;
611
612 typedef struct shadermodeinfo_s
613 {
614         const char *vertexfilename;
615         const char *geometryfilename;
616         const char *fragmentfilename;
617         const char *pretext;
618         const char *name;
619 }
620 shadermodeinfo_t;
621
622 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
623 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
624 {
625         {"#define USEDIFFUSE\n", " diffuse"},
626         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
627         {"#define USEVIEWTINT\n", " viewtint"},
628         {"#define USECOLORMAPPING\n", " colormapping"},
629         {"#define USESATURATION\n", " saturation"},
630         {"#define USEFOGINSIDE\n", " foginside"},
631         {"#define USEFOGOUTSIDE\n", " fogoutside"},
632         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
633         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
634         {"#define USEGAMMARAMPS\n", " gammaramps"},
635         {"#define USECUBEFILTER\n", " cubefilter"},
636         {"#define USEGLOW\n", " glow"},
637         {"#define USEBLOOM\n", " bloom"},
638         {"#define USESPECULAR\n", " specular"},
639         {"#define USEPOSTPROCESSING\n", " postprocessing"},
640         {"#define USEREFLECTION\n", " reflection"},
641         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
642         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
643         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
644         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
645         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
646         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
647         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
648         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
649         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
650         {"#define USEALPHAKILL\n", " alphakill"},
651         {"#define USEREFLECTCUBE\n", " reflectcube"},
652         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
653         {"#define USEBOUNCEGRID\n", " bouncegrid"},
654         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
655         {"#define USETRIPPY\n", " trippy"},
656 };
657
658 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
659 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
660 {
661         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
679 };
680
681 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
682 {
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701 };
702
703 struct r_glsl_permutation_s;
704 typedef struct r_glsl_permutation_s
705 {
706         /// hash lookup data
707         struct r_glsl_permutation_s *hashnext;
708         unsigned int mode;
709         unsigned int permutation;
710
711         /// indicates if we have tried compiling this permutation already
712         qboolean compiled;
713         /// 0 if compilation failed
714         int program;
715         // texture units assigned to each detected uniform
716         int tex_Texture_First;
717         int tex_Texture_Second;
718         int tex_Texture_GammaRamps;
719         int tex_Texture_Normal;
720         int tex_Texture_Color;
721         int tex_Texture_Gloss;
722         int tex_Texture_Glow;
723         int tex_Texture_SecondaryNormal;
724         int tex_Texture_SecondaryColor;
725         int tex_Texture_SecondaryGloss;
726         int tex_Texture_SecondaryGlow;
727         int tex_Texture_Pants;
728         int tex_Texture_Shirt;
729         int tex_Texture_FogHeightTexture;
730         int tex_Texture_FogMask;
731         int tex_Texture_Lightmap;
732         int tex_Texture_Deluxemap;
733         int tex_Texture_Attenuation;
734         int tex_Texture_Cube;
735         int tex_Texture_Refraction;
736         int tex_Texture_Reflection;
737         int tex_Texture_ShadowMap2D;
738         int tex_Texture_CubeProjection;
739         int tex_Texture_ScreenDepth;
740         int tex_Texture_ScreenNormalMap;
741         int tex_Texture_ScreenDiffuse;
742         int tex_Texture_ScreenSpecular;
743         int tex_Texture_ReflectMask;
744         int tex_Texture_ReflectCube;
745         int tex_Texture_BounceGrid;
746         /// locations of detected uniforms in program object, or -1 if not found
747         int loc_Texture_First;
748         int loc_Texture_Second;
749         int loc_Texture_GammaRamps;
750         int loc_Texture_Normal;
751         int loc_Texture_Color;
752         int loc_Texture_Gloss;
753         int loc_Texture_Glow;
754         int loc_Texture_SecondaryNormal;
755         int loc_Texture_SecondaryColor;
756         int loc_Texture_SecondaryGloss;
757         int loc_Texture_SecondaryGlow;
758         int loc_Texture_Pants;
759         int loc_Texture_Shirt;
760         int loc_Texture_FogHeightTexture;
761         int loc_Texture_FogMask;
762         int loc_Texture_Lightmap;
763         int loc_Texture_Deluxemap;
764         int loc_Texture_Attenuation;
765         int loc_Texture_Cube;
766         int loc_Texture_Refraction;
767         int loc_Texture_Reflection;
768         int loc_Texture_ShadowMap2D;
769         int loc_Texture_CubeProjection;
770         int loc_Texture_ScreenDepth;
771         int loc_Texture_ScreenNormalMap;
772         int loc_Texture_ScreenDiffuse;
773         int loc_Texture_ScreenSpecular;
774         int loc_Texture_ReflectMask;
775         int loc_Texture_ReflectCube;
776         int loc_Texture_BounceGrid;
777         int loc_Alpha;
778         int loc_BloomBlur_Parameters;
779         int loc_ClientTime;
780         int loc_Color_Ambient;
781         int loc_Color_Diffuse;
782         int loc_Color_Specular;
783         int loc_Color_Glow;
784         int loc_Color_Pants;
785         int loc_Color_Shirt;
786         int loc_DeferredColor_Ambient;
787         int loc_DeferredColor_Diffuse;
788         int loc_DeferredColor_Specular;
789         int loc_DeferredMod_Diffuse;
790         int loc_DeferredMod_Specular;
791         int loc_DistortScaleRefractReflect;
792         int loc_EyePosition;
793         int loc_FogColor;
794         int loc_FogHeightFade;
795         int loc_FogPlane;
796         int loc_FogPlaneViewDist;
797         int loc_FogRangeRecip;
798         int loc_LightColor;
799         int loc_LightDir;
800         int loc_LightPosition;
801         int loc_OffsetMapping_ScaleSteps;
802         int loc_OffsetMapping_LodDistance;
803         int loc_OffsetMapping_Bias;
804         int loc_PixelSize;
805         int loc_ReflectColor;
806         int loc_ReflectFactor;
807         int loc_ReflectOffset;
808         int loc_RefractColor;
809         int loc_Saturation;
810         int loc_ScreenCenterRefractReflect;
811         int loc_ScreenScaleRefractReflect;
812         int loc_ScreenToDepth;
813         int loc_ShadowMap_Parameters;
814         int loc_ShadowMap_TextureScale;
815         int loc_SpecularPower;
816         int loc_UserVec1;
817         int loc_UserVec2;
818         int loc_UserVec3;
819         int loc_UserVec4;
820         int loc_ViewTintColor;
821         int loc_ViewToLight;
822         int loc_ModelToLight;
823         int loc_TexMatrix;
824         int loc_BackgroundTexMatrix;
825         int loc_ModelViewProjectionMatrix;
826         int loc_ModelViewMatrix;
827         int loc_PixelToScreenTexCoord;
828         int loc_ModelToReflectCube;
829         int loc_ShadowMapMatrix;
830         int loc_BloomColorSubtract;
831         int loc_NormalmapScrollBlend;
832         int loc_BounceGridMatrix;
833         int loc_BounceGridIntensity;
834 }
835 r_glsl_permutation_t;
836
837 #define SHADERPERMUTATION_HASHSIZE 256
838
839
840 // non-degradable "lightweight" shader parameters to keep the permutations simpler
841 // these can NOT degrade! only use for simple stuff
842 enum
843 {
844         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
845         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
846         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
850         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
851         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
852 };
853 #define SHADERSTATICPARMS_COUNT 8
854
855 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
856 static int shaderstaticparms_count = 0;
857
858 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
859 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
860 qboolean R_CompileShader_CheckStaticParms(void)
861 {
862         static int r_compileshader_staticparms_save[1];
863         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
864         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
865
866         // detect all
867         if (r_glsl_saturation_redcompensate.integer)
868                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
869         if (r_glsl_vertextextureblend_usebothalphas.integer)
870                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
871         if (r_shadow_glossexact.integer)
872                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
873         if (r_glsl_postprocess.integer)
874         {
875                 if (r_glsl_postprocess_uservec1_enable.integer)
876                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
877                 if (r_glsl_postprocess_uservec2_enable.integer)
878                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
879                 if (r_glsl_postprocess_uservec3_enable.integer)
880                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
881                 if (r_glsl_postprocess_uservec4_enable.integer)
882                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
883         }
884         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
886         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
887 }
888
889 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
890         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
891                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
892         else \
893                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
894 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
895 {
896         shaderstaticparms_count = 0;
897
898         // emit all
899         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
907 }
908
909 /// information about each possible shader permutation
910 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
911 /// currently selected permutation
912 r_glsl_permutation_t *r_glsl_permutation;
913 /// storage for permutations linked in the hash table
914 memexpandablearray_t r_glsl_permutationarray;
915
916 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
917 {
918         //unsigned int hashdepth = 0;
919         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
920         r_glsl_permutation_t *p;
921         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
922         {
923                 if (p->mode == mode && p->permutation == permutation)
924                 {
925                         //if (hashdepth > 10)
926                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
927                         return p;
928                 }
929                 //hashdepth++;
930         }
931         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
932         p->mode = mode;
933         p->permutation = permutation;
934         p->hashnext = r_glsl_permutationhash[mode][hashindex];
935         r_glsl_permutationhash[mode][hashindex] = p;
936         //if (hashdepth > 10)
937         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
938         return p;
939 }
940
941 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
942 {
943         char *shaderstring;
944         if (!filename || !filename[0])
945                 return NULL;
946         if (!strcmp(filename, "glsl/default.glsl"))
947         {
948                 if (!glslshaderstring)
949                 {
950                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
951                         if (glslshaderstring)
952                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
953                         else
954                                 glslshaderstring = (char *)builtinshaderstring;
955                 }
956                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
957                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
958                 return shaderstring;
959         }
960         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
961         if (shaderstring)
962         {
963                 if (printfromdisknotice)
964                         Con_DPrintf("from disk %s... ", filename);
965                 return shaderstring;
966         }
967         return shaderstring;
968 }
969
970 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
971 {
972         int i;
973         int sampler;
974         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
975         char *vertexstring, *geometrystring, *fragmentstring;
976         char permutationname[256];
977         int vertstrings_count = 0;
978         int geomstrings_count = 0;
979         int fragstrings_count = 0;
980         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
981         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983
984         if (p->compiled)
985                 return;
986         p->compiled = true;
987         p->program = 0;
988
989         permutationname[0] = 0;
990         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
991         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
992         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
993
994         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
995
996         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
997         if(vid.support.gl20shaders130)
998         {
999                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1000                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1001                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1002                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1003                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1004                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1005         }
1006
1007         // the first pretext is which type of shader to compile as
1008         // (later these will all be bound together as a program object)
1009         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1010         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1011         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1012
1013         // the second pretext is the mode (for example a light source)
1014         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1015         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1016         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1017         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1018
1019         // now add all the permutation pretexts
1020         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1021         {
1022                 if (permutation & (1<<i))
1023                 {
1024                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1025                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1028                 }
1029                 else
1030                 {
1031                         // keep line numbers correct
1032                         vertstrings_list[vertstrings_count++] = "\n";
1033                         geomstrings_list[geomstrings_count++] = "\n";
1034                         fragstrings_list[fragstrings_count++] = "\n";
1035                 }
1036         }
1037
1038         // add static parms
1039         R_CompileShader_AddStaticParms(mode, permutation);
1040         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1041         vertstrings_count += shaderstaticparms_count;
1042         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1043         geomstrings_count += shaderstaticparms_count;
1044         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1045         fragstrings_count += shaderstaticparms_count;
1046
1047         // now append the shader text itself
1048         vertstrings_list[vertstrings_count++] = vertexstring;
1049         geomstrings_list[geomstrings_count++] = geometrystring;
1050         fragstrings_list[fragstrings_count++] = fragmentstring;
1051
1052         // if any sources were NULL, clear the respective list
1053         if (!vertexstring)
1054                 vertstrings_count = 0;
1055         if (!geometrystring)
1056                 geomstrings_count = 0;
1057         if (!fragmentstring)
1058                 fragstrings_count = 0;
1059
1060         // compile the shader program
1061         if (vertstrings_count + geomstrings_count + fragstrings_count)
1062                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1063         if (p->program)
1064         {
1065                 CHECKGLERROR
1066                 qglUseProgram(p->program);CHECKGLERROR
1067                 // look up all the uniform variable names we care about, so we don't
1068                 // have to look them up every time we set them
1069
1070                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1071                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1072                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1073                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1074                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1075                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1076                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1077                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1078                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1079                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1080                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1081                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1082                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1083                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1084                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1085                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1086                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1087                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1088                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1089                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1090                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1091                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1092                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1093                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1094                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1095                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1096                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1097                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1098                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1099                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1100                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1101                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1102                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1103                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1104                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1105                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1106                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1107                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1108                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1109                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1110                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1111                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1112                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1113                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1114                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1115                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1116                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1117                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1118                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1119                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1120                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1121                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1122                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1123                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1124                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1125                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1126                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1127                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1128                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1129                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1130                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1131                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1132                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1133                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1134                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1135                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1136                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1137                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1138                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1139                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1140                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1141                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1142                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1143                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1144                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1145                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1146                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1147                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1148                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1149                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1150                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1151                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1152                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1153                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1154                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1155                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1156                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1157                 // initialize the samplers to refer to the texture units we use
1158                 p->tex_Texture_First = -1;
1159                 p->tex_Texture_Second = -1;
1160                 p->tex_Texture_GammaRamps = -1;
1161                 p->tex_Texture_Normal = -1;
1162                 p->tex_Texture_Color = -1;
1163                 p->tex_Texture_Gloss = -1;
1164                 p->tex_Texture_Glow = -1;
1165                 p->tex_Texture_SecondaryNormal = -1;
1166                 p->tex_Texture_SecondaryColor = -1;
1167                 p->tex_Texture_SecondaryGloss = -1;
1168                 p->tex_Texture_SecondaryGlow = -1;
1169                 p->tex_Texture_Pants = -1;
1170                 p->tex_Texture_Shirt = -1;
1171                 p->tex_Texture_FogHeightTexture = -1;
1172                 p->tex_Texture_FogMask = -1;
1173                 p->tex_Texture_Lightmap = -1;
1174                 p->tex_Texture_Deluxemap = -1;
1175                 p->tex_Texture_Attenuation = -1;
1176                 p->tex_Texture_Cube = -1;
1177                 p->tex_Texture_Refraction = -1;
1178                 p->tex_Texture_Reflection = -1;
1179                 p->tex_Texture_ShadowMap2D = -1;
1180                 p->tex_Texture_CubeProjection = -1;
1181                 p->tex_Texture_ScreenDepth = -1;
1182                 p->tex_Texture_ScreenNormalMap = -1;
1183                 p->tex_Texture_ScreenDiffuse = -1;
1184                 p->tex_Texture_ScreenSpecular = -1;
1185                 p->tex_Texture_ReflectMask = -1;
1186                 p->tex_Texture_ReflectCube = -1;
1187                 p->tex_Texture_BounceGrid = -1;
1188                 sampler = 0;
1189                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1190                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1191                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1192                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1193                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1194                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1195                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1196                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1200                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1201                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1202                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1203                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1204                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1205                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1206                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1207                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1208                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1209                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1210                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1211                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1212                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1216                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1218                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1219                 CHECKGLERROR
1220                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1221         }
1222         else
1223                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1224
1225         // free the strings
1226         if (vertexstring)
1227                 Mem_Free(vertexstring);
1228         if (geometrystring)
1229                 Mem_Free(geometrystring);
1230         if (fragmentstring)
1231                 Mem_Free(fragmentstring);
1232 }
1233
1234 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1235 {
1236         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1237         if (r_glsl_permutation != perm)
1238         {
1239                 r_glsl_permutation = perm;
1240                 if (!r_glsl_permutation->program)
1241                 {
1242                         if (!r_glsl_permutation->compiled)
1243                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1244                         if (!r_glsl_permutation->program)
1245                         {
1246                                 // remove features until we find a valid permutation
1247                                 int i;
1248                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1249                                 {
1250                                         // reduce i more quickly whenever it would not remove any bits
1251                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1252                                         if (!(permutation & j))
1253                                                 continue;
1254                                         permutation -= j;
1255                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1256                                         if (!r_glsl_permutation->compiled)
1257                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1258                                         if (r_glsl_permutation->program)
1259                                                 break;
1260                                 }
1261                                 if (i >= SHADERPERMUTATION_COUNT)
1262                                 {
1263                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1264                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1265                                         qglUseProgram(0);CHECKGLERROR
1266                                         return; // no bit left to clear, entire mode is broken
1267                                 }
1268                         }
1269                 }
1270                 CHECKGLERROR
1271                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1272         }
1273         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1274         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1275         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1276 }
1277
1278 #ifdef SUPPORTD3D
1279
1280 #ifdef SUPPORTD3D
1281 #include <d3d9.h>
1282 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1283 extern D3DCAPS9 vid_d3d9caps;
1284 #endif
1285
1286 struct r_hlsl_permutation_s;
1287 typedef struct r_hlsl_permutation_s
1288 {
1289         /// hash lookup data
1290         struct r_hlsl_permutation_s *hashnext;
1291         unsigned int mode;
1292         unsigned int permutation;
1293
1294         /// indicates if we have tried compiling this permutation already
1295         qboolean compiled;
1296         /// NULL if compilation failed
1297         IDirect3DVertexShader9 *vertexshader;
1298         IDirect3DPixelShader9 *pixelshader;
1299 }
1300 r_hlsl_permutation_t;
1301
1302 typedef enum D3DVSREGISTER_e
1303 {
1304         D3DVSREGISTER_TexMatrix = 0, // float4x4
1305         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1306         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1307         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1308         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1309         D3DVSREGISTER_ModelToLight = 20, // float4x4
1310         D3DVSREGISTER_EyePosition = 24,
1311         D3DVSREGISTER_FogPlane = 25,
1312         D3DVSREGISTER_LightDir = 26,
1313         D3DVSREGISTER_LightPosition = 27,
1314 }
1315 D3DVSREGISTER_t;
1316
1317 typedef enum D3DPSREGISTER_e
1318 {
1319         D3DPSREGISTER_Alpha = 0,
1320         D3DPSREGISTER_BloomBlur_Parameters = 1,
1321         D3DPSREGISTER_ClientTime = 2,
1322         D3DPSREGISTER_Color_Ambient = 3,
1323         D3DPSREGISTER_Color_Diffuse = 4,
1324         D3DPSREGISTER_Color_Specular = 5,
1325         D3DPSREGISTER_Color_Glow = 6,
1326         D3DPSREGISTER_Color_Pants = 7,
1327         D3DPSREGISTER_Color_Shirt = 8,
1328         D3DPSREGISTER_DeferredColor_Ambient = 9,
1329         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1330         D3DPSREGISTER_DeferredColor_Specular = 11,
1331         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1332         D3DPSREGISTER_DeferredMod_Specular = 13,
1333         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1334         D3DPSREGISTER_EyePosition = 15, // unused
1335         D3DPSREGISTER_FogColor = 16,
1336         D3DPSREGISTER_FogHeightFade = 17,
1337         D3DPSREGISTER_FogPlane = 18,
1338         D3DPSREGISTER_FogPlaneViewDist = 19,
1339         D3DPSREGISTER_FogRangeRecip = 20,
1340         D3DPSREGISTER_LightColor = 21,
1341         D3DPSREGISTER_LightDir = 22, // unused
1342         D3DPSREGISTER_LightPosition = 23,
1343         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1344         D3DPSREGISTER_PixelSize = 25,
1345         D3DPSREGISTER_ReflectColor = 26,
1346         D3DPSREGISTER_ReflectFactor = 27,
1347         D3DPSREGISTER_ReflectOffset = 28,
1348         D3DPSREGISTER_RefractColor = 29,
1349         D3DPSREGISTER_Saturation = 30,
1350         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1351         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1352         D3DPSREGISTER_ScreenToDepth = 33,
1353         D3DPSREGISTER_ShadowMap_Parameters = 34,
1354         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1355         D3DPSREGISTER_SpecularPower = 36,
1356         D3DPSREGISTER_UserVec1 = 37,
1357         D3DPSREGISTER_UserVec2 = 38,
1358         D3DPSREGISTER_UserVec3 = 39,
1359         D3DPSREGISTER_UserVec4 = 40,
1360         D3DPSREGISTER_ViewTintColor = 41,
1361         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1362         D3DPSREGISTER_BloomColorSubtract = 43,
1363         D3DPSREGISTER_ViewToLight = 44, // float4x4
1364         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1365         D3DPSREGISTER_NormalmapScrollBlend = 52,
1366         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1367         D3DPSREGISTER_OffsetMapping_Bias = 54,
1368         // next at 54
1369 }
1370 D3DPSREGISTER_t;
1371
1372 /// information about each possible shader permutation
1373 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1374 /// currently selected permutation
1375 r_hlsl_permutation_t *r_hlsl_permutation;
1376 /// storage for permutations linked in the hash table
1377 memexpandablearray_t r_hlsl_permutationarray;
1378
1379 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1380 {
1381         //unsigned int hashdepth = 0;
1382         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1383         r_hlsl_permutation_t *p;
1384         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1385         {
1386                 if (p->mode == mode && p->permutation == permutation)
1387                 {
1388                         //if (hashdepth > 10)
1389                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1390                         return p;
1391                 }
1392                 //hashdepth++;
1393         }
1394         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1395         p->mode = mode;
1396         p->permutation = permutation;
1397         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1398         r_hlsl_permutationhash[mode][hashindex] = p;
1399         //if (hashdepth > 10)
1400         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1401         return p;
1402 }
1403
1404 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1405 {
1406         char *shaderstring;
1407         if (!filename || !filename[0])
1408                 return NULL;
1409         if (!strcmp(filename, "hlsl/default.hlsl"))
1410         {
1411                 if (!hlslshaderstring)
1412                 {
1413                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1414                         if (hlslshaderstring)
1415                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1416                         else
1417                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1418                 }
1419                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1420                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1421                 return shaderstring;
1422         }
1423         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424         if (shaderstring)
1425         {
1426                 if (printfromdisknotice)
1427                         Con_DPrintf("from disk %s... ", filename);
1428                 return shaderstring;
1429         }
1430         return shaderstring;
1431 }
1432
1433 #include <d3dx9.h>
1434 //#include <d3dx9shader.h>
1435 //#include <d3dx9mesh.h>
1436
1437 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1438 {
1439         DWORD *vsbin = NULL;
1440         DWORD *psbin = NULL;
1441         fs_offset_t vsbinsize;
1442         fs_offset_t psbinsize;
1443 //      IDirect3DVertexShader9 *vs = NULL;
1444 //      IDirect3DPixelShader9 *ps = NULL;
1445         ID3DXBuffer *vslog = NULL;
1446         ID3DXBuffer *vsbuffer = NULL;
1447         ID3DXConstantTable *vsconstanttable = NULL;
1448         ID3DXBuffer *pslog = NULL;
1449         ID3DXBuffer *psbuffer = NULL;
1450         ID3DXConstantTable *psconstanttable = NULL;
1451         int vsresult = 0;
1452         int psresult = 0;
1453         char temp[MAX_INPUTLINE];
1454         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1455         qboolean debugshader = gl_paranoid.integer != 0;
1456         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1457         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1458         if (!debugshader)
1459         {
1460                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1461                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1462         }
1463         if ((!vsbin && vertstring) || (!psbin && fragstring))
1464         {
1465                 const char* dllnames_d3dx9 [] =
1466                 {
1467                         "d3dx9_43.dll",
1468                         "d3dx9_42.dll",
1469                         "d3dx9_41.dll",
1470                         "d3dx9_40.dll",
1471                         "d3dx9_39.dll",
1472                         "d3dx9_38.dll",
1473                         "d3dx9_37.dll",
1474                         "d3dx9_36.dll",
1475                         "d3dx9_35.dll",
1476                         "d3dx9_34.dll",
1477                         "d3dx9_33.dll",
1478                         "d3dx9_32.dll",
1479                         "d3dx9_31.dll",
1480                         "d3dx9_30.dll",
1481                         "d3dx9_29.dll",
1482                         "d3dx9_28.dll",
1483                         "d3dx9_27.dll",
1484                         "d3dx9_26.dll",
1485                         "d3dx9_25.dll",
1486                         "d3dx9_24.dll",
1487                         NULL
1488                 };
1489                 dllhandle_t d3dx9_dll = NULL;
1490                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1491                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1492                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1493                 dllfunction_t d3dx9_dllfuncs[] =
1494                 {
1495                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1496                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1497                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1498                         {NULL, NULL}
1499                 };
1500                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1501                 {
1502                         DWORD shaderflags = 0;
1503                         if (debugshader)
1504                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1505                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1506                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1507                         if (vertstring && vertstring[0])
1508                         {
1509                                 if (debugshader)
1510                                 {
1511 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1512 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1513                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1514                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1515                                 }
1516                                 else
1517                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1518                                 if (vsbuffer)
1519                                 {
1520                                         vsbinsize = vsbuffer->GetBufferSize();
1521                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1522                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1523                                         vsbuffer->Release();
1524                                 }
1525                                 if (vslog)
1526                                 {
1527                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1528                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1529                                         vslog->Release();
1530                                 }
1531                         }
1532                         if (fragstring && fragstring[0])
1533                         {
1534                                 if (debugshader)
1535                                 {
1536 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1537 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1538                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1539                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1540                                 }
1541                                 else
1542                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1543                                 if (psbuffer)
1544                                 {
1545                                         psbinsize = psbuffer->GetBufferSize();
1546                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1547                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1548                                         psbuffer->Release();
1549                                 }
1550                                 if (pslog)
1551                                 {
1552                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1553                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1554                                         pslog->Release();
1555                                 }
1556                         }
1557                         Sys_UnloadLibrary(&d3dx9_dll);
1558                 }
1559                 else
1560                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1561         }
1562         if (vsbin && psbin)
1563         {
1564                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1565                 if (FAILED(vsresult))
1566                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1567                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1568                 if (FAILED(psresult))
1569                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1570         }
1571         // free the shader data
1572         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1573         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1574 }
1575
1576 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1577 {
1578         int i;
1579         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1580         int vertstring_length = 0;
1581         int geomstring_length = 0;
1582         int fragstring_length = 0;
1583         char *t;
1584         char *vertexstring, *geometrystring, *fragmentstring;
1585         char *vertstring, *geomstring, *fragstring;
1586         char permutationname[256];
1587         char cachename[256];
1588         int vertstrings_count = 0;
1589         int geomstrings_count = 0;
1590         int fragstrings_count = 0;
1591         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1592         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1593         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594
1595         if (p->compiled)
1596                 return;
1597         p->compiled = true;
1598         p->vertexshader = NULL;
1599         p->pixelshader = NULL;
1600
1601         permutationname[0] = 0;
1602         cachename[0] = 0;
1603         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1604         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1605         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1606
1607         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1608         strlcat(cachename, "hlsl/", sizeof(cachename));
1609
1610         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1611         vertstrings_count = 0;
1612         geomstrings_count = 0;
1613         fragstrings_count = 0;
1614         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1615         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1616         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1617
1618         // the first pretext is which type of shader to compile as
1619         // (later these will all be bound together as a program object)
1620         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1621         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1622         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1623
1624         // the second pretext is the mode (for example a light source)
1625         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1626         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1627         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1628         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1629         strlcat(cachename, modeinfo->name, sizeof(cachename));
1630
1631         // now add all the permutation pretexts
1632         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1633         {
1634                 if (permutation & (1<<i))
1635                 {
1636                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1637                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1640                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1641                 }
1642                 else
1643                 {
1644                         // keep line numbers correct
1645                         vertstrings_list[vertstrings_count++] = "\n";
1646                         geomstrings_list[geomstrings_count++] = "\n";
1647                         fragstrings_list[fragstrings_count++] = "\n";
1648                 }
1649         }
1650
1651         // add static parms
1652         R_CompileShader_AddStaticParms(mode, permutation);
1653         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1654         vertstrings_count += shaderstaticparms_count;
1655         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1656         geomstrings_count += shaderstaticparms_count;
1657         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         fragstrings_count += shaderstaticparms_count;
1659
1660         // replace spaces in the cachename with _ characters
1661         for (i = 0;cachename[i];i++)
1662                 if (cachename[i] == ' ')
1663                         cachename[i] = '_';
1664
1665         // now append the shader text itself
1666         vertstrings_list[vertstrings_count++] = vertexstring;
1667         geomstrings_list[geomstrings_count++] = geometrystring;
1668         fragstrings_list[fragstrings_count++] = fragmentstring;
1669
1670         // if any sources were NULL, clear the respective list
1671         if (!vertexstring)
1672                 vertstrings_count = 0;
1673         if (!geometrystring)
1674                 geomstrings_count = 0;
1675         if (!fragmentstring)
1676                 fragstrings_count = 0;
1677
1678         vertstring_length = 0;
1679         for (i = 0;i < vertstrings_count;i++)
1680                 vertstring_length += strlen(vertstrings_list[i]);
1681         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1682         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1683                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1684
1685         geomstring_length = 0;
1686         for (i = 0;i < geomstrings_count;i++)
1687                 geomstring_length += strlen(geomstrings_list[i]);
1688         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1689         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1690                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1691
1692         fragstring_length = 0;
1693         for (i = 0;i < fragstrings_count;i++)
1694                 fragstring_length += strlen(fragstrings_list[i]);
1695         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1696         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1697                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1698
1699         // try to load the cached shader, or generate one
1700         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1701
1702         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1703                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1704         else
1705                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1706
1707         // free the strings
1708         if (vertstring)
1709                 Mem_Free(vertstring);
1710         if (geomstring)
1711                 Mem_Free(geomstring);
1712         if (fragstring)
1713                 Mem_Free(fragstring);
1714         if (vertexstring)
1715                 Mem_Free(vertexstring);
1716         if (geometrystring)
1717                 Mem_Free(geometrystring);
1718         if (fragmentstring)
1719                 Mem_Free(fragmentstring);
1720 }
1721
1722 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1723 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1724 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);}
1725 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);}
1726 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);}
1727 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);}
1728
1729 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1730 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1731 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);}
1732 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);}
1733 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);}
1734 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);}
1735
1736 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1737 {
1738         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1739         if (r_hlsl_permutation != perm)
1740         {
1741                 r_hlsl_permutation = perm;
1742                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1743                 {
1744                         if (!r_hlsl_permutation->compiled)
1745                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1746                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747                         {
1748                                 // remove features until we find a valid permutation
1749                                 int i;
1750                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1751                                 {
1752                                         // reduce i more quickly whenever it would not remove any bits
1753                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1754                                         if (!(permutation & j))
1755                                                 continue;
1756                                         permutation -= j;
1757                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1758                                         if (!r_hlsl_permutation->compiled)
1759                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1760                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1761                                                 break;
1762                                 }
1763                                 if (i >= SHADERPERMUTATION_COUNT)
1764                                 {
1765                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         return; // no bit left to clear, entire mode is broken
1768                                 }
1769                         }
1770                 }
1771                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1772                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1773         }
1774         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1775         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1776         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1777 }
1778 #endif
1779
1780 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1781 {
1782         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1783         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1784         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1785         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1786 }
1787
1788 void R_GLSL_Restart_f(void)
1789 {
1790         unsigned int i, limit;
1791         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1792                 Mem_Free(glslshaderstring);
1793         glslshaderstring = NULL;
1794         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1795                 Mem_Free(hlslshaderstring);
1796         hlslshaderstring = NULL;
1797         switch(vid.renderpath)
1798         {
1799         case RENDERPATH_D3D9:
1800 #ifdef SUPPORTD3D
1801                 {
1802                         r_hlsl_permutation_t *p;
1803                         r_hlsl_permutation = NULL;
1804                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1805                         for (i = 0;i < limit;i++)
1806                         {
1807                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1808                                 {
1809                                         if (p->vertexshader)
1810                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1811                                         if (p->pixelshader)
1812                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1813                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1814                                 }
1815                         }
1816                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1817                 }
1818 #endif
1819                 break;
1820         case RENDERPATH_D3D10:
1821                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1822                 break;
1823         case RENDERPATH_D3D11:
1824                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1825                 break;
1826         case RENDERPATH_GL20:
1827         case RENDERPATH_GLES2:
1828                 {
1829                         r_glsl_permutation_t *p;
1830                         r_glsl_permutation = NULL;
1831                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1832                         for (i = 0;i < limit;i++)
1833                         {
1834                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1835                                 {
1836                                         GL_Backend_FreeProgram(p->program);
1837                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1838                                 }
1839                         }
1840                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1841                 }
1842                 break;
1843         case RENDERPATH_GL11:
1844         case RENDERPATH_GL13:
1845         case RENDERPATH_GLES1:
1846                 break;
1847         case RENDERPATH_SOFT:
1848                 break;
1849         }
1850 }
1851
1852 void R_GLSL_DumpShader_f(void)
1853 {
1854         int i;
1855         qfile_t *file;
1856
1857         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1858         if (file)
1859         {
1860                 FS_Print(file, "/* The engine may define the following macros:\n");
1861                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1862                 for (i = 0;i < SHADERMODE_COUNT;i++)
1863                         FS_Print(file, glslshadermodeinfo[i].pretext);
1864                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1865                         FS_Print(file, shaderpermutationinfo[i].pretext);
1866                 FS_Print(file, "*/\n");
1867                 FS_Print(file, builtinshaderstring);
1868                 FS_Close(file);
1869                 Con_Printf("glsl/default.glsl written\n");
1870         }
1871         else
1872                 Con_Printf("failed to write to glsl/default.glsl\n");
1873
1874         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1875         if (file)
1876         {
1877                 FS_Print(file, "/* The engine may define the following macros:\n");
1878                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1879                 for (i = 0;i < SHADERMODE_COUNT;i++)
1880                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1881                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1882                         FS_Print(file, shaderpermutationinfo[i].pretext);
1883                 FS_Print(file, "*/\n");
1884                 FS_Print(file, builtinhlslshaderstring);
1885                 FS_Close(file);
1886                 Con_Printf("hlsl/default.hlsl written\n");
1887         }
1888         else
1889                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1890 }
1891
1892 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1893 {
1894         unsigned int permutation = 0;
1895         if (r_trippy.integer && !notrippy)
1896                 permutation |= SHADERPERMUTATION_TRIPPY;
1897         permutation |= SHADERPERMUTATION_VIEWTINT;
1898         if (first)
1899                 permutation |= SHADERPERMUTATION_DIFFUSE;
1900         if (second)
1901                 permutation |= SHADERPERMUTATION_SPECULAR;
1902         if (texturemode == GL_MODULATE)
1903                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1904         else if (texturemode == GL_ADD)
1905                 permutation |= SHADERPERMUTATION_GLOW;
1906         else if (texturemode == GL_DECAL)
1907                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1908         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1909                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1910         if (!second)
1911                 texturemode = GL_MODULATE;
1912         if (vid.allowalphatocoverage)
1913                 GL_AlphaToCoverage(false);
1914         switch (vid.renderpath)
1915         {
1916         case RENDERPATH_D3D9:
1917 #ifdef SUPPORTD3D
1918                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1919                 R_Mesh_TexBind(GL20TU_FIRST , first );
1920                 R_Mesh_TexBind(GL20TU_SECOND, second);
1921                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1922                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1923 #endif
1924                 break;
1925         case RENDERPATH_D3D10:
1926                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927                 break;
1928         case RENDERPATH_D3D11:
1929                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_GL20:
1932         case RENDERPATH_GLES2:
1933                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1934                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1936                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1937                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1938                 break;
1939         case RENDERPATH_GL13:
1940         case RENDERPATH_GLES1:
1941                 R_Mesh_TexBind(0, first );
1942                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1943                 R_Mesh_TexBind(1, second);
1944                 if (second)
1945                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1946                 break;
1947         case RENDERPATH_GL11:
1948                 R_Mesh_TexBind(0, first );
1949                 break;
1950         case RENDERPATH_SOFT:
1951                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1952                 R_Mesh_TexBind(GL20TU_FIRST , first );
1953                 R_Mesh_TexBind(GL20TU_SECOND, second);
1954                 break;
1955         }
1956 }
1957
1958 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1959 {
1960         unsigned int permutation = 0;
1961         if (r_trippy.integer && !notrippy)
1962                 permutation |= SHADERPERMUTATION_TRIPPY;
1963         if (vid.allowalphatocoverage)
1964                 GL_AlphaToCoverage(false);
1965         switch (vid.renderpath)
1966         {
1967         case RENDERPATH_D3D9:
1968 #ifdef SUPPORTD3D
1969                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1970 #endif
1971                 break;
1972         case RENDERPATH_D3D10:
1973                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1974                 break;
1975         case RENDERPATH_D3D11:
1976                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1977                 break;
1978         case RENDERPATH_GL20:
1979         case RENDERPATH_GLES2:
1980                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1981                 break;
1982         case RENDERPATH_GL13:
1983         case RENDERPATH_GLES1:
1984                 R_Mesh_TexBind(0, 0);
1985                 R_Mesh_TexBind(1, 0);
1986                 break;
1987         case RENDERPATH_GL11:
1988                 R_Mesh_TexBind(0, 0);
1989                 break;
1990         case RENDERPATH_SOFT:
1991                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1992                 break;
1993         }
1994 }
1995
1996 void R_SetupShader_ShowDepth(qboolean notrippy)
1997 {
1998         int permutation = 0;
1999         if (r_trippy.integer && !notrippy)
2000                 permutation |= SHADERPERMUTATION_TRIPPY;
2001         if (vid.allowalphatocoverage)
2002                 GL_AlphaToCoverage(false);
2003         switch (vid.renderpath)
2004         {
2005         case RENDERPATH_D3D9:
2006 #ifdef SUPPORTHLSL
2007                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2008 #endif
2009                 break;
2010         case RENDERPATH_D3D10:
2011                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2012                 break;
2013         case RENDERPATH_D3D11:
2014                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2015                 break;
2016         case RENDERPATH_GL20:
2017         case RENDERPATH_GLES2:
2018                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2019                 break;
2020         case RENDERPATH_GL13:
2021         case RENDERPATH_GLES1:
2022                 break;
2023         case RENDERPATH_GL11:
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2027                 break;
2028         }
2029 }
2030
2031 extern qboolean r_shadow_usingdeferredprepass;
2032 extern cvar_t r_shadow_deferred_8bitrange;
2033 extern rtexture_t *r_shadow_attenuationgradienttexture;
2034 extern rtexture_t *r_shadow_attenuation2dtexture;
2035 extern rtexture_t *r_shadow_attenuation3dtexture;
2036 extern qboolean r_shadow_usingshadowmap2d;
2037 extern qboolean r_shadow_usingshadowmaportho;
2038 extern float r_shadow_shadowmap_texturescale[2];
2039 extern float r_shadow_shadowmap_parameters[4];
2040 extern qboolean r_shadow_shadowmapvsdct;
2041 extern qboolean r_shadow_shadowmapsampler;
2042 extern int r_shadow_shadowmappcf;
2043 extern rtexture_t *r_shadow_shadowmap2dtexture;
2044 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2045 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2046 extern matrix4x4_t r_shadow_shadowmapmatrix;
2047 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2048 extern int r_shadow_prepass_width;
2049 extern int r_shadow_prepass_height;
2050 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2051 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2052 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2053 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2054 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2055
2056 #define BLENDFUNC_ALLOWS_COLORMOD      1
2057 #define BLENDFUNC_ALLOWS_FOG           2
2058 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2059 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2060 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2061 static int R_BlendFuncFlags(int src, int dst)
2062 {
2063         int r = 0;
2064
2065         // a blendfunc allows colormod if:
2066         // a) it can never keep the destination pixel invariant, or
2067         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2068         // this is to prevent unintended side effects from colormod
2069
2070         // a blendfunc allows fog if:
2071         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2072         // this is to prevent unintended side effects from fog
2073
2074         // these checks are the output of fogeval.pl
2075
2076         r |= BLENDFUNC_ALLOWS_COLORMOD;
2077         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2078         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2079         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2081         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2082         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2086         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2089         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2092         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098
2099         return r;
2100 }
2101
2102 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)
2103 {
2104         // select a permutation of the lighting shader appropriate to this
2105         // combination of texture, entity, light source, and fogging, only use the
2106         // minimum features necessary to avoid wasting rendering time in the
2107         // fragment shader on features that are not being used
2108         unsigned int permutation = 0;
2109         unsigned int mode = 0;
2110         int blendfuncflags;
2111         static float dummy_colormod[3] = {1, 1, 1};
2112         float *colormod = rsurface.colormod;
2113         float m16f[16];
2114         matrix4x4_t tempmatrix;
2115         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2116         if (r_trippy.integer && !notrippy)
2117                 permutation |= SHADERPERMUTATION_TRIPPY;
2118         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2119                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2120         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2121                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2122         if (rsurfacepass == RSURFPASS_BACKGROUND)
2123         {
2124                 // distorted background
2125                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2126                 {
2127                         mode = SHADERMODE_WATER;
2128                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2129                         {
2130                                 // this is the right thing to do for wateralpha
2131                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2132                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2133                         }
2134                         else
2135                         {
2136                                 // this is the right thing to do for entity alpha
2137                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2138                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                         }
2140                 }
2141                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2142                 {
2143                         mode = SHADERMODE_REFRACTION;
2144                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                 }
2147                 else
2148                 {
2149                         mode = SHADERMODE_GENERIC;
2150                         permutation |= SHADERPERMUTATION_DIFFUSE;
2151                         GL_BlendFunc(GL_ONE, GL_ZERO);
2152                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2153                 }
2154                 if (vid.allowalphatocoverage)
2155                         GL_AlphaToCoverage(false);
2156         }
2157         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2158         {
2159                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2160                 {
2161                         switch(rsurface.texture->offsetmapping)
2162                         {
2163                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_OFF: break;
2167                         }
2168                 }
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 // normalmap (deferred prepass), may use alpha test on diffuse
2172                 mode = SHADERMODE_DEFERREDGEOMETRY;
2173                 GL_BlendFunc(GL_ONE, GL_ZERO);
2174                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2175                 if (vid.allowalphatocoverage)
2176                         GL_AlphaToCoverage(false);
2177         }
2178         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2179         {
2180                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2181                 {
2182                         switch(rsurface.texture->offsetmapping)
2183                         {
2184                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2185                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_OFF: break;
2188                         }
2189                 }
2190                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2191                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2192                 // light source
2193                 mode = SHADERMODE_LIGHTSOURCE;
2194                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2195                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2196                 if (diffusescale > 0)
2197                         permutation |= SHADERPERMUTATION_DIFFUSE;
2198                 if (specularscale > 0)
2199                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2200                 if (r_refdef.fogenabled)
2201                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2202                 if (rsurface.texture->colormapping)
2203                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2204                 if (r_shadow_usingshadowmap2d)
2205                 {
2206                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2207                         if(r_shadow_shadowmapvsdct)
2208                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2209
2210                         if (r_shadow_shadowmapsampler)
2211                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2212                         if (r_shadow_shadowmappcf > 1)
2213                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2214                         else if (r_shadow_shadowmappcf)
2215                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2216                 }
2217                 if (rsurface.texture->reflectmasktexture)
2218                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2219                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2220                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2221                 if (vid.allowalphatocoverage)
2222                         GL_AlphaToCoverage(false);
2223         }
2224         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2225         {
2226                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2227                 {
2228                         switch(rsurface.texture->offsetmapping)
2229                         {
2230                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2231                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2232                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233                         case OFFSETMAPPING_OFF: break;
2234                         }
2235                 }
2236                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2237                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2238                 // unshaded geometry (fullbright or ambient model lighting)
2239                 mode = SHADERMODE_FLATCOLOR;
2240                 ambientscale = diffusescale = specularscale = 0;
2241                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2242                         permutation |= SHADERPERMUTATION_GLOW;
2243                 if (r_refdef.fogenabled)
2244                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2245                 if (rsurface.texture->colormapping)
2246                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2247                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2248                 {
2249                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2250                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2251
2252                         if (r_shadow_shadowmapsampler)
2253                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2254                         if (r_shadow_shadowmappcf > 1)
2255                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2256                         else if (r_shadow_shadowmappcf)
2257                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2260                         permutation |= SHADERPERMUTATION_REFLECTION;
2261                 if (rsurface.texture->reflectmasktexture)
2262                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2263                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2264                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 // when using alphatocoverage, we don't need alphakill
2266                 if (vid.allowalphatocoverage)
2267                 {
2268                         if (r_transparent_alphatocoverage.integer)
2269                         {
2270                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2271                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2272                         }
2273                         else
2274                                 GL_AlphaToCoverage(false);
2275                 }
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2278         {
2279                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 // directional model lighting
2292                 mode = SHADERMODE_LIGHTDIRECTION;
2293                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2294                         permutation |= SHADERPERMUTATION_GLOW;
2295                 permutation |= SHADERPERMUTATION_DIFFUSE;
2296                 if (specularscale > 0)
2297                         permutation |= SHADERPERMUTATION_SPECULAR;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmapsampler)
2308                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2309                         if (r_shadow_shadowmappcf > 1)
2310                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2311                         else if (r_shadow_shadowmappcf)
2312                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2315                         permutation |= SHADERPERMUTATION_REFLECTION;
2316                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2317                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2318                 if (rsurface.texture->reflectmasktexture)
2319                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2321                 {
2322                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2323                         if (r_shadow_bouncegriddirectional)
2324                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2325                 }
2326                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 // when using alphatocoverage, we don't need alphakill
2329                 if (vid.allowalphatocoverage)
2330                 {
2331                         if (r_transparent_alphatocoverage.integer)
2332                         {
2333                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2334                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2335                         }
2336                         else
2337                                 GL_AlphaToCoverage(false);
2338                 }
2339         }
2340         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2341         {
2342                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2343                 {
2344                         switch(rsurface.texture->offsetmapping)
2345                         {
2346                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2347                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_OFF: break;
2350                         }
2351                 }
2352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354                 // ambient model lighting
2355                 mode = SHADERMODE_LIGHTDIRECTION;
2356                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2357                         permutation |= SHADERPERMUTATION_GLOW;
2358                 if (r_refdef.fogenabled)
2359                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2360                 if (rsurface.texture->colormapping)
2361                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2362                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2363                 {
2364                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2365                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2366
2367                         if (r_shadow_shadowmapsampler)
2368                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2369                         if (r_shadow_shadowmappcf > 1)
2370                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2371                         else if (r_shadow_shadowmappcf)
2372                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2373                 }
2374                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2375                         permutation |= SHADERPERMUTATION_REFLECTION;
2376                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2377                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2378                 if (rsurface.texture->reflectmasktexture)
2379                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2380                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2381                 {
2382                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2383                         if (r_shadow_bouncegriddirectional)
2384                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2385                 }
2386                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2387                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 // when using alphatocoverage, we don't need alphakill
2389                 if (vid.allowalphatocoverage)
2390                 {
2391                         if (r_transparent_alphatocoverage.integer)
2392                         {
2393                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2394                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2395                         }
2396                         else
2397                                 GL_AlphaToCoverage(false);
2398                 }
2399         }
2400         else
2401         {
2402                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2403                 {
2404                         switch(rsurface.texture->offsetmapping)
2405                         {
2406                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2407                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2408                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_OFF: break;
2410                         }
2411                 }
2412                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2413                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2414                 // lightmapped wall
2415                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2416                         permutation |= SHADERPERMUTATION_GLOW;
2417                 if (r_refdef.fogenabled)
2418                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2419                 if (rsurface.texture->colormapping)
2420                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2421                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2422                 {
2423                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2424                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2425
2426                         if (r_shadow_shadowmapsampler)
2427                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2428                         if (r_shadow_shadowmappcf > 1)
2429                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2430                         else if (r_shadow_shadowmappcf)
2431                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2432                 }
2433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434                         permutation |= SHADERPERMUTATION_REFLECTION;
2435                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2436                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437                 if (rsurface.texture->reflectmasktexture)
2438                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439                 if (FAKELIGHT_ENABLED)
2440                 {
2441                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442                         mode = SHADERMODE_FAKELIGHT;
2443                         permutation |= SHADERPERMUTATION_DIFFUSE;
2444                         if (specularscale > 0)
2445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446                 }
2447                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448                 {
2449                         // deluxemapping (light direction texture)
2450                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452                         else
2453                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (specularscale > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 2)
2459                 {
2460                         // fake deluxemapping (uniform light direction in tangentspace)
2461                         if (rsurface.uselightmaptexture)
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2463                         else
2464                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2465                         permutation |= SHADERPERMUTATION_DIFFUSE;
2466                         if (specularscale > 0)
2467                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468                 }
2469                 else if (rsurface.uselightmaptexture)
2470                 {
2471                         // ordinary lightmapping (q1bsp, q3bsp)
2472                         mode = SHADERMODE_LIGHTMAP;
2473                 }
2474                 else
2475                 {
2476                         // ordinary vertex coloring (q3bsp)
2477                         mode = SHADERMODE_VERTEXCOLOR;
2478                 }
2479                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2480                 {
2481                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482                         if (r_shadow_bouncegriddirectional)
2483                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2484                 }
2485                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487                 // when using alphatocoverage, we don't need alphakill
2488                 if (vid.allowalphatocoverage)
2489                 {
2490                         if (r_transparent_alphatocoverage.integer)
2491                         {
2492                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2494                         }
2495                         else
2496                                 GL_AlphaToCoverage(false);
2497                 }
2498         }
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2500                 colormod = dummy_colormod;
2501         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2502                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2503         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2504                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2505         switch(vid.renderpath)
2506         {
2507         case RENDERPATH_D3D9:
2508 #ifdef SUPPORTD3D
2509                 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);
2510                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2511                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2512                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2513                 if (mode == SHADERMODE_LIGHTSOURCE)
2514                 {
2515                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2516                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2517                 }
2518                 else
2519                 {
2520                         if (mode == SHADERMODE_LIGHTDIRECTION)
2521                         {
2522                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2523                         }
2524                 }
2525                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2527                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2528                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2530
2531                 if (mode == SHADERMODE_LIGHTSOURCE)
2532                 {
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2538
2539                         // additive passes are only darkened by fog, not tinted
2540                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2541                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_FLATCOLOR)
2546                         {
2547                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2548                         }
2549                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 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]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2553                                 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);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2557                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2558                         }
2559                         else
2560                         {
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2563                                 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);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2566                         }
2567                         // additive passes are only darkened by fog, not tinted
2568                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2570                         else
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2572                         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);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2579                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2580                         if (mode == SHADERMODE_WATER)
2581                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2582                 }
2583                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2584                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2585                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2586                 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));
2587                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2588                 if (rsurface.texture->pantstexture)
2589                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2590                 else
2591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2592                 if (rsurface.texture->shirttexture)
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2594                 else
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2596                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2599                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2601                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2602                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2605                         );
2606                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2609                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2610
2611                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2612                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2613                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2614                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2619                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2620                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2621                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2622                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2623                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2624                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2625                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2626                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2627                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2628                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2629                 {
2630                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2631                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2632                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2633                 }
2634                 else
2635                 {
2636                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2637                 }
2638 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2639 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2640                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2641                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2642                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2643                 {
2644                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2645                         if (rsurface.rtlight)
2646                         {
2647                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2648                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2649                         }
2650                 }
2651 #endif
2652                 break;
2653         case RENDERPATH_D3D10:
2654                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2655                 break;
2656         case RENDERPATH_D3D11:
2657                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2658                 break;
2659         case RENDERPATH_GL20:
2660         case RENDERPATH_GLES2:
2661                 if (!vid.useinterleavedarrays)
2662                 {
2663                         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);
2664                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2665                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2671                 }
2672                 else
2673                 {
2674                         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);
2675                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2676                 }
2677                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2678                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2679                 if (mode == SHADERMODE_LIGHTSOURCE)
2680                 {
2681                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2682                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2683                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2684                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2685                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2686                         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);
2687         
2688                         // additive passes are only darkened by fog, not tinted
2689                         if (r_glsl_permutation->loc_FogColor >= 0)
2690                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2691                         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);
2692                 }
2693                 else
2694                 {
2695                         if (mode == SHADERMODE_FLATCOLOR)
2696                         {
2697                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2698                         }
2699                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2700                         {
2701                                 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]);
2702                                 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]);
2703                                 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);
2704                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2705                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2706                                 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]);
2707                                 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]);
2708                         }
2709                         else
2710                         {
2711                                 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]);
2712                                 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]);
2713                                 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);
2714                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2715                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2716                         }
2717                         // additive passes are only darkened by fog, not tinted
2718                         if (r_glsl_permutation->loc_FogColor >= 0)
2719                         {
2720                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2721                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2722                                 else
2723                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2724                         }
2725                         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);
2726                         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]);
2727                         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]);
2728                         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]);
2729                         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]);
2730                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2731                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2732                         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);
2733                         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]);
2734                 }
2735                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2736                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2737                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2738                 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]);
2739                 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]);
2740
2741                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2742                 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));
2743                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2744                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2745                 {
2746                         if (rsurface.texture->pantstexture)
2747                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2748                         else
2749                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2750                 }
2751                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2752                 {
2753                         if (rsurface.texture->shirttexture)
2754                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2755                         else
2756                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2757                 }
2758                 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]);
2759                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2760                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2761                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2762                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2763                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2764                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2765                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2766                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2767                         );
2768                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2769                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2770                 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]);
2771                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2772                 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);}
2773                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2774
2775                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2776                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2777                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2778                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2779                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2780                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2781                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2782                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2783                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2784                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2785                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2786                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2787                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2788                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2789                 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);
2790                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2791                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2792                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2793                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2794                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2795                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2796                 {
2797                         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);
2798                         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);
2799                         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);
2800                 }
2801                 else
2802                 {
2803                         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);
2804                 }
2805                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2806                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2807                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2808                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2809                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2810                 {
2811                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2812                         if (rsurface.rtlight)
2813                         {
2814                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2815                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2816                         }
2817                 }
2818                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2819                 CHECKGLERROR
2820                 break;
2821         case RENDERPATH_GL11:
2822         case RENDERPATH_GL13:
2823         case RENDERPATH_GLES1:
2824                 break;
2825         case RENDERPATH_SOFT:
2826                 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);
2827                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2828                 R_SetupShader_SetPermutationSoft(mode, permutation);
2829                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2830                 if (mode == SHADERMODE_LIGHTSOURCE)
2831                 {
2832                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2835                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2837                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2838         
2839                         // additive passes are only darkened by fog, not tinted
2840                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2841                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2842                 }
2843                 else
2844                 {
2845                         if (mode == SHADERMODE_FLATCOLOR)
2846                         {
2847                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2848                         }
2849                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2850                         {
2851                                 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]);
2852                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2853                                 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);
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2856                                 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]);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2858                         }
2859                         else
2860                         {
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2863                                 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);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2866                         }
2867                         // additive passes are only darkened by fog, not tinted
2868                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2870                         else
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2872                         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);
2873                         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]);
2874                         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]);
2875                         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]);
2876                         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]);
2877                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2878                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2879                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2880                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2881                 }
2882                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2883                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2884                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2885                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2886                 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]);
2887
2888                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2889                 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));
2890                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2891                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2892                 {
2893                         if (rsurface.texture->pantstexture)
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2895                         else
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2897                 }
2898                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2899                 {
2900                         if (rsurface.texture->shirttexture)
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2902                         else
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2904                 }
2905                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2906                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2907                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2908                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2909                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2910                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2911                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2912                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2913                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2914                         );
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2917                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2918                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2919
2920                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2921                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2922                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2923                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2924                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2926                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2927                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2928                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2929                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2930                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2931                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2932                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2933                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2934                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2935                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2936                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2937                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2938                 {
2939                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2940                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2941                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2942                 }
2943                 else
2944                 {
2945                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2946                 }
2947 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2948 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2949                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2950                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2951                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2952                 {
2953                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2954                         if (rsurface.rtlight)
2955                         {
2956                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2957                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2958                         }
2959                 }
2960                 break;
2961         }
2962 }
2963
2964 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2965 {
2966         // select a permutation of the lighting shader appropriate to this
2967         // combination of texture, entity, light source, and fogging, only use the
2968         // minimum features necessary to avoid wasting rendering time in the
2969         // fragment shader on features that are not being used
2970         unsigned int permutation = 0;
2971         unsigned int mode = 0;
2972         const float *lightcolorbase = rtlight->currentcolor;
2973         float ambientscale = rtlight->ambientscale;
2974         float diffusescale = rtlight->diffusescale;
2975         float specularscale = rtlight->specularscale;
2976         // this is the location of the light in view space
2977         vec3_t viewlightorigin;
2978         // this transforms from view space (camera) to light space (cubemap)
2979         matrix4x4_t viewtolight;
2980         matrix4x4_t lighttoview;
2981         float viewtolight16f[16];
2982         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2983         // light source
2984         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2985         if (rtlight->currentcubemap != r_texture_whitecube)
2986                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2987         if (diffusescale > 0)
2988                 permutation |= SHADERPERMUTATION_DIFFUSE;
2989         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2990                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2991         if (r_shadow_usingshadowmap2d)
2992         {
2993                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2994                 if (r_shadow_shadowmapvsdct)
2995                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2996
2997                 if (r_shadow_shadowmapsampler)
2998                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2999                 if (r_shadow_shadowmappcf > 1)
3000                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3001                 else if (r_shadow_shadowmappcf)
3002                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3003         }
3004         if (vid.allowalphatocoverage)
3005                 GL_AlphaToCoverage(false);
3006         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3007         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3008         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3009         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3010         switch(vid.renderpath)
3011         {
3012         case RENDERPATH_D3D9:
3013 #ifdef SUPPORTD3D
3014                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3015                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3016                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3017                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3019                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3020                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3021                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3022                 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);
3023                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3024                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3025
3026                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3027                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3028                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3029                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3030                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3031                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3032 #endif
3033                 break;
3034         case RENDERPATH_D3D10:
3035                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3036                 break;
3037         case RENDERPATH_D3D11:
3038                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3039                 break;
3040         case RENDERPATH_GL20:
3041         case RENDERPATH_GLES2:
3042                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3043                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3044                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3045                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3046                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3047                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3048                 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]);
3049                 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]);
3050                 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);
3051                 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]);
3052                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3053
3054                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3055                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3056                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3057                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3058                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3059                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3060                 break;
3061         case RENDERPATH_GL11:
3062         case RENDERPATH_GL13:
3063         case RENDERPATH_GLES1:
3064                 break;
3065         case RENDERPATH_SOFT:
3066                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3067                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3068                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3069                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3070                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3071                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3072                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3073                 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]);
3074                 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);
3075                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3076                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3077
3078                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3079                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3080                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3081                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3082                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3083                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3084                 break;
3085         }
3086 }
3087
3088 #define SKINFRAME_HASH 1024
3089
3090 typedef struct
3091 {
3092         int loadsequence; // incremented each level change
3093         memexpandablearray_t array;
3094         skinframe_t *hash[SKINFRAME_HASH];
3095 }
3096 r_skinframe_t;
3097 r_skinframe_t r_skinframe;
3098
3099 void R_SkinFrame_PrepareForPurge(void)
3100 {
3101         r_skinframe.loadsequence++;
3102         // wrap it without hitting zero
3103         if (r_skinframe.loadsequence >= 200)
3104                 r_skinframe.loadsequence = 1;
3105 }
3106
3107 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3108 {
3109         if (!skinframe)
3110                 return;
3111         // mark the skinframe as used for the purging code
3112         skinframe->loadsequence = r_skinframe.loadsequence;
3113 }
3114
3115 void R_SkinFrame_Purge(void)
3116 {
3117         int i;
3118         skinframe_t *s;
3119         for (i = 0;i < SKINFRAME_HASH;i++)
3120         {
3121                 for (s = r_skinframe.hash[i];s;s = s->next)
3122                 {
3123                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3124                         {
3125                                 if (s->merged == s->base)
3126                                         s->merged = NULL;
3127                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3128                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3129                                 R_PurgeTexture(s->merged);s->merged = NULL;
3130                                 R_PurgeTexture(s->base  );s->base   = NULL;
3131                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3132                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3133                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3134                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3135                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3136                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3137                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3138                                 s->loadsequence = 0;
3139                         }
3140                 }
3141         }
3142 }
3143
3144 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3145         skinframe_t *item;
3146         char basename[MAX_QPATH];
3147
3148         Image_StripImageExtension(name, basename, sizeof(basename));
3149
3150         if( last == NULL ) {
3151                 int hashindex;
3152                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3153                 item = r_skinframe.hash[hashindex];
3154         } else {
3155                 item = last->next;
3156         }
3157
3158         // linearly search through the hash bucket
3159         for( ; item ; item = item->next ) {
3160                 if( !strcmp( item->basename, basename ) ) {
3161                         return item;
3162                 }
3163         }
3164         return NULL;
3165 }
3166
3167 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3168 {
3169         skinframe_t *item;
3170         int hashindex;
3171         char basename[MAX_QPATH];
3172
3173         Image_StripImageExtension(name, basename, sizeof(basename));
3174
3175         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3176         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3177                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3178                         break;
3179
3180         if (!item) {
3181                 rtexture_t *dyntexture;
3182                 // check whether its a dynamic texture
3183                 dyntexture = CL_GetDynTexture( basename );
3184                 if (!add && !dyntexture)
3185                         return NULL;
3186                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3187                 memset(item, 0, sizeof(*item));
3188                 strlcpy(item->basename, basename, sizeof(item->basename));
3189                 item->base = dyntexture; // either NULL or dyntexture handle
3190                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3191                 item->comparewidth = comparewidth;
3192                 item->compareheight = compareheight;
3193                 item->comparecrc = comparecrc;
3194                 item->next = r_skinframe.hash[hashindex];
3195                 r_skinframe.hash[hashindex] = item;
3196         }
3197         else if (textureflags & TEXF_FORCE_RELOAD)
3198         {
3199                 rtexture_t *dyntexture;
3200                 // check whether its a dynamic texture
3201                 dyntexture = CL_GetDynTexture( basename );
3202                 if (!add && !dyntexture)
3203                         return NULL;
3204                 if (item->merged == item->base)
3205                         item->merged = NULL;
3206                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3207                 R_PurgeTexture(item->stain );item->stain  = NULL;
3208                 R_PurgeTexture(item->merged);item->merged = NULL;
3209                 R_PurgeTexture(item->base  );item->base   = NULL;
3210                 R_PurgeTexture(item->pants );item->pants  = NULL;
3211                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3212                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3213                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3214                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3215                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3216         R_PurgeTexture(item->reflect);item->reflect = NULL;
3217                 item->loadsequence = 0;
3218         }
3219         else if( item->base == NULL )
3220         {
3221                 rtexture_t *dyntexture;
3222                 // check whether its a dynamic texture
3223                 // 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]
3224                 dyntexture = CL_GetDynTexture( basename );
3225                 item->base = dyntexture; // either NULL or dyntexture handle
3226         }
3227
3228         R_SkinFrame_MarkUsed(item);
3229         return item;
3230 }
3231
3232 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3233         { \
3234                 unsigned long long avgcolor[5], wsum; \
3235                 int pix, comp, w; \
3236                 avgcolor[0] = 0; \
3237                 avgcolor[1] = 0; \
3238                 avgcolor[2] = 0; \
3239                 avgcolor[3] = 0; \
3240                 avgcolor[4] = 0; \
3241                 wsum = 0; \
3242                 for(pix = 0; pix < cnt; ++pix) \
3243                 { \
3244                         w = 0; \
3245                         for(comp = 0; comp < 3; ++comp) \
3246                                 w += getpixel; \
3247                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3248                         { \
3249                                 ++wsum; \
3250                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3251                                 w = getpixel; \
3252                                 for(comp = 0; comp < 3; ++comp) \
3253                                         avgcolor[comp] += getpixel * w; \
3254                                 avgcolor[3] += w; \
3255                         } \
3256                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3257                         avgcolor[4] += getpixel; \
3258                 } \
3259                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3260                         avgcolor[3] = 1; \
3261                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3262                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3263                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3264                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3265         }
3266
3267 extern cvar_t gl_picmip;
3268 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3269 {
3270         int j;
3271         unsigned char *pixels;
3272         unsigned char *bumppixels;
3273         unsigned char *basepixels = NULL;
3274         int basepixels_width = 0;
3275         int basepixels_height = 0;
3276         skinframe_t *skinframe;
3277         rtexture_t *ddsbase = NULL;
3278         qboolean ddshasalpha = false;
3279         float ddsavgcolor[4];
3280         char basename[MAX_QPATH];
3281         int miplevel = R_PicmipForFlags(textureflags);
3282         int savemiplevel = miplevel;
3283         int mymiplevel;
3284
3285         if (cls.state == ca_dedicated)
3286                 return NULL;
3287
3288         // return an existing skinframe if already loaded
3289         // if loading of the first image fails, don't make a new skinframe as it
3290         // would cause all future lookups of this to be missing
3291         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3292         if (skinframe && skinframe->base)
3293                 return skinframe;
3294
3295         Image_StripImageExtension(name, basename, sizeof(basename));
3296
3297         // check for DDS texture file first
3298         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3299         {
3300                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3301                 if (basepixels == NULL)
3302                         return NULL;
3303         }
3304
3305         // FIXME handle miplevel
3306
3307         if (developer_loading.integer)
3308                 Con_Printf("loading skin \"%s\"\n", name);
3309
3310         // we've got some pixels to store, so really allocate this new texture now
3311         if (!skinframe)
3312                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3313         textureflags &= ~TEXF_FORCE_RELOAD;
3314         skinframe->stain = NULL;
3315         skinframe->merged = NULL;
3316         skinframe->base = NULL;
3317         skinframe->pants = NULL;
3318         skinframe->shirt = NULL;
3319         skinframe->nmap = NULL;
3320         skinframe->gloss = NULL;
3321         skinframe->glow = NULL;
3322         skinframe->fog = NULL;
3323         skinframe->reflect = NULL;
3324         skinframe->hasalpha = false;
3325
3326         if (ddsbase)
3327         {
3328                 skinframe->base = ddsbase;
3329                 skinframe->hasalpha = ddshasalpha;
3330                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3331                 if (r_loadfog && skinframe->hasalpha)
3332                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3333                 //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]);
3334         }
3335         else
3336         {
3337                 basepixels_width = image_width;
3338                 basepixels_height = image_height;
3339                 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);
3340                 if (textureflags & TEXF_ALPHA)
3341                 {
3342                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3343                         {
3344                                 if (basepixels[j] < 255)
3345                                 {
3346                                         skinframe->hasalpha = true;
3347                                         break;
3348                                 }
3349                         }
3350                         if (r_loadfog && skinframe->hasalpha)
3351                         {
3352                                 // has transparent pixels
3353                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3354                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3355                                 {
3356                                         pixels[j+0] = 255;
3357                                         pixels[j+1] = 255;
3358                                         pixels[j+2] = 255;
3359                                         pixels[j+3] = basepixels[j+3];
3360                                 }
3361                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3362                                 Mem_Free(pixels);
3363                         }
3364                 }
3365                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3366 #ifndef USE_GLES2
3367                 //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]);
3368                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3369                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3370                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3371                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3372 #endif
3373         }
3374
3375         if (r_loaddds)
3376         {
3377                 mymiplevel = savemiplevel;
3378                 if (r_loadnormalmap)
3379                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3380                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3381                 if (r_loadgloss)
3382                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3383                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3384                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3385                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3386         }
3387
3388         // _norm is the name used by tenebrae and has been adopted as standard
3389         if (r_loadnormalmap && skinframe->nmap == NULL)
3390         {
3391                 mymiplevel = savemiplevel;
3392                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3393                 {
3394                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3395                         Mem_Free(pixels);
3396                         pixels = NULL;
3397                 }
3398                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3399                 {
3400                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3401                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3402                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3403                         Mem_Free(pixels);
3404                         Mem_Free(bumppixels);
3405                 }
3406                 else if (r_shadow_bumpscale_basetexture.value > 0)
3407                 {
3408                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3409                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3410                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3411                         Mem_Free(pixels);
3412                 }
3413 #ifndef USE_GLES2
3414                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3415                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3416 #endif
3417         }
3418
3419         // _luma is supported only for tenebrae compatibility
3420         // _glow is the preferred name
3421         mymiplevel = savemiplevel;
3422         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3423         {
3424                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%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);
3425 #ifndef USE_GLES2
3426                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3427                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3428 #endif
3429                 Mem_Free(pixels);pixels = NULL;
3430         }
3431
3432         mymiplevel = savemiplevel;
3433         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3434         {
3435                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%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);
3436 #ifndef USE_GLES2
3437                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3438                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3439 #endif
3440                 Mem_Free(pixels);
3441                 pixels = NULL;
3442         }
3443
3444         mymiplevel = savemiplevel;
3445         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3446         {
3447                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%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);
3448 #ifndef USE_GLES2
3449                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3450                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3451 #endif
3452                 Mem_Free(pixels);
3453                 pixels = NULL;
3454         }
3455
3456         mymiplevel = savemiplevel;
3457         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3458         {
3459                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%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);
3460 #ifndef USE_GLES2
3461                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3462                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3463 #endif
3464                 Mem_Free(pixels);
3465                 pixels = NULL;
3466         }
3467
3468         mymiplevel = savemiplevel;
3469         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3470         {
3471                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%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);
3472 #ifndef USE_GLES2
3473                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3474                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3475 #endif
3476                 Mem_Free(pixels);
3477                 pixels = NULL;
3478         }
3479
3480         if (basepixels)
3481                 Mem_Free(basepixels);
3482
3483         return skinframe;
3484 }
3485
3486 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3487 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3488 {
3489         int i;
3490         unsigned char *temp1, *temp2;
3491         skinframe_t *skinframe;
3492
3493         if (cls.state == ca_dedicated)
3494                 return NULL;
3495
3496         // if already loaded just return it, otherwise make a new skinframe
3497         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3498         if (skinframe && skinframe->base)
3499                 return skinframe;
3500         textureflags &= ~TEXF_FORCE_RELOAD;
3501
3502         skinframe->stain = NULL;
3503         skinframe->merged = NULL;
3504         skinframe->base = NULL;
3505         skinframe->pants = NULL;
3506         skinframe->shirt = NULL;
3507         skinframe->nmap = NULL;
3508         skinframe->gloss = NULL;
3509         skinframe->glow = NULL;
3510         skinframe->fog = NULL;
3511         skinframe->reflect = NULL;
3512         skinframe->hasalpha = false;
3513
3514         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3515         if (!skindata)
3516                 return NULL;
3517
3518         if (developer_loading.integer)
3519                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3520
3521         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3522         {
3523                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3524                 temp2 = temp1 + width * height * 4;
3525                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3527                 Mem_Free(temp1);
3528         }
3529         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3530         if (textureflags & TEXF_ALPHA)
3531         {
3532                 for (i = 3;i < width * height * 4;i += 4)
3533                 {
3534                         if (skindata[i] < 255)
3535                         {
3536                                 skinframe->hasalpha = true;
3537                                 break;
3538                         }
3539                 }
3540                 if (r_loadfog && skinframe->hasalpha)
3541                 {
3542                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3543                         memcpy(fogpixels, skindata, width * height * 4);
3544                         for (i = 0;i < width * height * 4;i += 4)
3545                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3546                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3547                         Mem_Free(fogpixels);
3548                 }
3549         }
3550
3551         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3552         //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]);
3553
3554         return skinframe;
3555 }
3556
3557 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3558 {
3559         int i;
3560         int featuresmask;
3561         skinframe_t *skinframe;
3562
3563         if (cls.state == ca_dedicated)
3564                 return NULL;
3565
3566         // if already loaded just return it, otherwise make a new skinframe
3567         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3568         if (skinframe && skinframe->base)
3569                 return skinframe;
3570         textureflags &= ~TEXF_FORCE_RELOAD;
3571
3572         skinframe->stain = NULL;
3573         skinframe->merged = NULL;
3574         skinframe->base = NULL;
3575         skinframe->pants = NULL;
3576         skinframe->shirt = NULL;
3577         skinframe->nmap = NULL;
3578         skinframe->gloss = NULL;
3579         skinframe->glow = NULL;
3580         skinframe->fog = NULL;
3581         skinframe->reflect = NULL;
3582         skinframe->hasalpha = false;
3583
3584         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3585         if (!skindata)
3586                 return NULL;
3587
3588         if (developer_loading.integer)
3589                 Con_Printf("loading quake skin \"%s\"\n", name);
3590
3591         // 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)
3592         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3593         memcpy(skinframe->qpixels, skindata, width*height);
3594         skinframe->qwidth = width;
3595         skinframe->qheight = height;
3596
3597         featuresmask = 0;
3598         for (i = 0;i < width * height;i++)
3599                 featuresmask |= palette_featureflags[skindata[i]];
3600
3601         skinframe->hasalpha = false;
3602         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3603         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3604         skinframe->qgeneratemerged = true;
3605         skinframe->qgeneratebase = skinframe->qhascolormapping;
3606         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3607
3608         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3609         //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]);
3610
3611         return skinframe;
3612 }
3613
3614 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3615 {
3616         int width;
3617         int height;
3618         unsigned char *skindata;
3619
3620         if (!skinframe->qpixels)
3621                 return;
3622
3623         if (!skinframe->qhascolormapping)
3624                 colormapped = false;
3625
3626         if (colormapped)
3627         {
3628                 if (!skinframe->qgeneratebase)
3629                         return;
3630         }
3631         else
3632         {
3633                 if (!skinframe->qgeneratemerged)
3634                         return;
3635         }
3636
3637         width = skinframe->qwidth;
3638         height = skinframe->qheight;
3639         skindata = skinframe->qpixels;
3640
3641         if (skinframe->qgeneratenmap)
3642         {
3643                 unsigned char *temp1, *temp2;
3644                 skinframe->qgeneratenmap = false;
3645                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3646                 temp2 = temp1 + width * height * 4;
3647                 // use either a custom palette or the quake palette
3648                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3649                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3650                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3651                 Mem_Free(temp1);
3652         }
3653
3654         if (skinframe->qgenerateglow)
3655         {
3656                 skinframe->qgenerateglow = false;
3657                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3658         }
3659
3660         if (colormapped)
3661         {
3662                 skinframe->qgeneratebase = false;
3663                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%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);
3664                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3665                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3666         }
3667         else
3668         {
3669                 skinframe->qgeneratemerged = false;
3670                 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);
3671         }
3672
3673         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3674         {
3675                 Mem_Free(skinframe->qpixels);
3676                 skinframe->qpixels = NULL;
3677         }
3678 }
3679
3680 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)
3681 {
3682         int i;
3683         skinframe_t *skinframe;
3684
3685         if (cls.state == ca_dedicated)
3686                 return NULL;
3687
3688         // if already loaded just return it, otherwise make a new skinframe
3689         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3690         if (skinframe && skinframe->base)
3691                 return skinframe;
3692         textureflags &= ~TEXF_FORCE_RELOAD;
3693
3694         skinframe->stain = NULL;
3695         skinframe->merged = NULL;
3696         skinframe->base = NULL;
3697         skinframe->pants = NULL;
3698         skinframe->shirt = NULL;
3699         skinframe->nmap = NULL;
3700         skinframe->gloss = NULL;
3701         skinframe->glow = NULL;
3702         skinframe->fog = NULL;
3703         skinframe->reflect = NULL;
3704         skinframe->hasalpha = false;
3705
3706         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3707         if (!skindata)
3708                 return NULL;
3709
3710         if (developer_loading.integer)
3711                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3712
3713         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3714         if (textureflags & TEXF_ALPHA)
3715         {
3716                 for (i = 0;i < width * height;i++)
3717                 {
3718                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3719                         {
3720                                 skinframe->hasalpha = true;
3721                                 break;
3722                         }
3723                 }
3724                 if (r_loadfog && skinframe->hasalpha)
3725                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3726         }
3727
3728         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3729         //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]);
3730
3731         return skinframe;
3732 }
3733
3734 skinframe_t *R_SkinFrame_LoadMissing(void)
3735 {
3736         skinframe_t *skinframe;
3737
3738         if (cls.state == ca_dedicated)
3739                 return NULL;
3740
3741         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3742         skinframe->stain = NULL;
3743         skinframe->merged = NULL;
3744         skinframe->base = NULL;
3745         skinframe->pants = NULL;
3746         skinframe->shirt = NULL;
3747         skinframe->nmap = NULL;
3748         skinframe->gloss = NULL;
3749         skinframe->glow = NULL;
3750         skinframe->fog = NULL;
3751         skinframe->reflect = NULL;
3752         skinframe->hasalpha = false;
3753
3754         skinframe->avgcolor[0] = rand() / RAND_MAX;
3755         skinframe->avgcolor[1] = rand() / RAND_MAX;
3756         skinframe->avgcolor[2] = rand() / RAND_MAX;
3757         skinframe->avgcolor[3] = 1;
3758
3759         return skinframe;
3760 }
3761
3762 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3763 typedef struct suffixinfo_s
3764 {
3765         const char *suffix;
3766         qboolean flipx, flipy, flipdiagonal;
3767 }
3768 suffixinfo_t;
3769 static suffixinfo_t suffix[3][6] =
3770 {
3771         {
3772                 {"px",   false, false, false},
3773                 {"nx",   false, false, false},
3774                 {"py",   false, false, false},
3775                 {"ny",   false, false, false},
3776                 {"pz",   false, false, false},
3777                 {"nz",   false, false, false}
3778         },
3779         {
3780                 {"posx", false, false, false},
3781                 {"negx", false, false, false},
3782                 {"posy", false, false, false},
3783                 {"negy", false, false, false},
3784                 {"posz", false, false, false},
3785                 {"negz", false, false, false}
3786         },
3787         {
3788                 {"rt",    true, false,  true},
3789                 {"lf",   false,  true,  true},
3790                 {"ft",    true,  true, false},
3791                 {"bk",   false, false, false},
3792                 {"up",    true, false,  true},
3793                 {"dn",    true, false,  true}
3794         }
3795 };
3796
3797 static int componentorder[4] = {0, 1, 2, 3};
3798
3799 rtexture_t *R_LoadCubemap(const char *basename)
3800 {
3801         int i, j, cubemapsize;
3802         unsigned char *cubemappixels, *image_buffer;
3803         rtexture_t *cubemaptexture;
3804         char name[256];
3805         // must start 0 so the first loadimagepixels has no requested width/height
3806         cubemapsize = 0;
3807         cubemappixels = NULL;
3808         cubemaptexture = NULL;
3809         // keep trying different suffix groups (posx, px, rt) until one loads
3810         for (j = 0;j < 3 && !cubemappixels;j++)
3811         {
3812                 // load the 6 images in the suffix group
3813                 for (i = 0;i < 6;i++)
3814                 {
3815                         // generate an image name based on the base and and suffix
3816                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3817                         // load it
3818                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3819                         {
3820                                 // an image loaded, make sure width and height are equal
3821                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3822                                 {
3823                                         // if this is the first image to load successfully, allocate the cubemap memory
3824                                         if (!cubemappixels && image_width >= 1)
3825                                         {
3826                                                 cubemapsize = image_width;
3827                                                 // note this clears to black, so unavailable sides are black
3828                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3829                                         }
3830                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3831                                         if (cubemappixels)
3832                                                 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);
3833                                 }
3834                                 else
3835                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3836                                 // free the image
3837                                 Mem_Free(image_buffer);
3838                         }
3839                 }
3840         }
3841         // if a cubemap loaded, upload it
3842         if (cubemappixels)
3843         {
3844                 if (developer_loading.integer)
3845                         Con_Printf("loading cubemap \"%s\"\n", basename);
3846
3847                 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);
3848                 Mem_Free(cubemappixels);
3849         }
3850         else
3851         {
3852                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3853                 if (developer_loading.integer)
3854                 {
3855                         Con_Printf("(tried tried images ");
3856                         for (j = 0;j < 3;j++)
3857                                 for (i = 0;i < 6;i++)
3858                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3859                         Con_Print(" and was unable to find any of them).\n");
3860                 }
3861         }
3862         return cubemaptexture;
3863 }
3864
3865 rtexture_t *R_GetCubemap(const char *basename)
3866 {
3867         int i;
3868         for (i = 0;i < r_texture_numcubemaps;i++)
3869                 if (r_texture_cubemaps[i] != NULL)
3870                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3871                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3872         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3873                 return r_texture_whitecube;
3874         r_texture_numcubemaps++;
3875         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3876         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3877         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3878         return r_texture_cubemaps[i]->texture;
3879 }
3880
3881 void R_FreeCubemap(const char *basename)
3882 {
3883         int i;
3884
3885         for (i = 0;i < r_texture_numcubemaps;i++)
3886         {
3887                 if (r_texture_cubemaps[i] != NULL)
3888                 {
3889                         if (r_texture_cubemaps[i]->texture)
3890                         {
3891                                 if (developer_loading.integer)
3892                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3893                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3894                                 Mem_Free(r_texture_cubemaps[i]);
3895                                 r_texture_cubemaps[i] = NULL;
3896                         }
3897                 }
3898         }
3899 }
3900
3901 void R_FreeCubemaps(void)
3902 {
3903         int i;
3904         for (i = 0;i < r_texture_numcubemaps;i++)
3905         {
3906                 if (developer_loading.integer)
3907                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3908                 if (r_texture_cubemaps[i] != NULL)
3909                 {
3910                         if (r_texture_cubemaps[i]->texture)
3911                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3912                         Mem_Free(r_texture_cubemaps[i]);
3913                 }
3914         }
3915         r_texture_numcubemaps = 0;
3916 }
3917
3918 void R_Main_FreeViewCache(void)
3919 {
3920         if (r_refdef.viewcache.entityvisible)
3921                 Mem_Free(r_refdef.viewcache.entityvisible);
3922         if (r_refdef.viewcache.world_pvsbits)
3923                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3924         if (r_refdef.viewcache.world_leafvisible)
3925                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3926         if (r_refdef.viewcache.world_surfacevisible)
3927                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3928         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3929 }
3930
3931 void R_Main_ResizeViewCache(void)
3932 {
3933         int numentities = r_refdef.scene.numentities;
3934         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3935         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3936         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3937         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3938         if (r_refdef.viewcache.maxentities < numentities)
3939         {
3940                 r_refdef.viewcache.maxentities = numentities;
3941                 if (r_refdef.viewcache.entityvisible)
3942                         Mem_Free(r_refdef.viewcache.entityvisible);
3943                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3944         }
3945         if (r_refdef.viewcache.world_numclusters != numclusters)
3946         {
3947                 r_refdef.viewcache.world_numclusters = numclusters;
3948                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3949                 if (r_refdef.viewcache.world_pvsbits)
3950                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3951                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3952         }
3953         if (r_refdef.viewcache.world_numleafs != numleafs)
3954         {
3955                 r_refdef.viewcache.world_numleafs = numleafs;
3956                 if (r_refdef.viewcache.world_leafvisible)
3957                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3958                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3959         }
3960         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3961         {
3962                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3963                 if (r_refdef.viewcache.world_surfacevisible)
3964                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3965                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3966         }
3967 }
3968
3969 extern rtexture_t *loadingscreentexture;
3970 void gl_main_start(void)
3971 {
3972         loadingscreentexture = NULL;
3973         r_texture_blanknormalmap = NULL;
3974         r_texture_white = NULL;
3975         r_texture_grey128 = NULL;
3976         r_texture_black = NULL;
3977         r_texture_whitecube = NULL;
3978         r_texture_normalizationcube = NULL;
3979         r_texture_fogattenuation = NULL;
3980         r_texture_fogheighttexture = NULL;
3981         r_texture_gammaramps = NULL;
3982         r_texture_numcubemaps = 0;
3983
3984         r_loaddds = r_texture_dds_load.integer != 0;
3985         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3986
3987         switch(vid.renderpath)
3988         {
3989         case RENDERPATH_GL20:
3990         case RENDERPATH_D3D9:
3991         case RENDERPATH_D3D10:
3992         case RENDERPATH_D3D11:
3993         case RENDERPATH_SOFT:
3994         case RENDERPATH_GLES2:
3995                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3996                 Cvar_SetValueQuick(&gl_combine, 1);
3997                 Cvar_SetValueQuick(&r_glsl, 1);
3998                 r_loadnormalmap = true;
3999                 r_loadgloss = true;
4000                 r_loadfog = false;
4001                 break;
4002         case RENDERPATH_GL13:
4003         case RENDERPATH_GLES1:
4004                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4005                 Cvar_SetValueQuick(&gl_combine, 1);
4006                 Cvar_SetValueQuick(&r_glsl, 0);
4007                 r_loadnormalmap = false;
4008                 r_loadgloss = false;
4009                 r_loadfog = true;
4010                 break;
4011         case RENDERPATH_GL11:
4012                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4013                 Cvar_SetValueQuick(&gl_combine, 0);
4014                 Cvar_SetValueQuick(&r_glsl, 0);
4015                 r_loadnormalmap = false;
4016                 r_loadgloss = false;
4017                 r_loadfog = true;
4018                 break;
4019         }
4020
4021         R_AnimCache_Free();
4022         R_FrameData_Reset();
4023
4024         r_numqueries = 0;
4025         r_maxqueries = 0;
4026         memset(r_queries, 0, sizeof(r_queries));
4027
4028         r_qwskincache = NULL;
4029         r_qwskincache_size = 0;
4030
4031         // due to caching of texture_t references, the collision cache must be reset
4032         Collision_Cache_Reset(true);
4033
4034         // set up r_skinframe loading system for textures
4035         memset(&r_skinframe, 0, sizeof(r_skinframe));
4036         r_skinframe.loadsequence = 1;
4037         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4038
4039         r_main_texturepool = R_AllocTexturePool();
4040         R_BuildBlankTextures();
4041         R_BuildNoTexture();
4042         if (vid.support.arb_texture_cube_map)
4043         {
4044                 R_BuildWhiteCube();
4045                 R_BuildNormalizationCube();
4046         }
4047         r_texture_fogattenuation = NULL;
4048         r_texture_fogheighttexture = NULL;
4049         r_texture_gammaramps = NULL;
4050         //r_texture_fogintensity = NULL;
4051         memset(&r_fb, 0, sizeof(r_fb));
4052         r_glsl_permutation = NULL;
4053         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4054         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4055         glslshaderstring = NULL;
4056 #ifdef SUPPORTD3D
4057         r_hlsl_permutation = NULL;
4058         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4059         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4060 #endif
4061         hlslshaderstring = NULL;
4062         memset(&r_svbsp, 0, sizeof (r_svbsp));
4063
4064         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4065         r_texture_numcubemaps = 0;
4066
4067         r_refdef.fogmasktable_density = 0;
4068 }
4069
4070 void gl_main_shutdown(void)
4071 {
4072         R_AnimCache_Free();
4073         R_FrameData_Reset();
4074
4075         R_Main_FreeViewCache();
4076
4077         switch(vid.renderpath)
4078         {
4079         case RENDERPATH_GL11:
4080         case RENDERPATH_GL13:
4081         case RENDERPATH_GL20:
4082         case RENDERPATH_GLES1:
4083         case RENDERPATH_GLES2:
4084 #ifdef GL_SAMPLES_PASSED_ARB
4085                 if (r_maxqueries)
4086                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4087 #endif
4088                 break;
4089         case RENDERPATH_D3D9:
4090                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4091                 break;
4092         case RENDERPATH_D3D10:
4093                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4094                 break;
4095         case RENDERPATH_D3D11:
4096                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4097                 break;
4098         case RENDERPATH_SOFT:
4099                 break;
4100         }
4101
4102         r_numqueries = 0;
4103         r_maxqueries = 0;
4104         memset(r_queries, 0, sizeof(r_queries));
4105
4106         r_qwskincache = NULL;
4107         r_qwskincache_size = 0;
4108
4109         // clear out the r_skinframe state
4110         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4111         memset(&r_skinframe, 0, sizeof(r_skinframe));
4112
4113         if (r_svbsp.nodes)
4114                 Mem_Free(r_svbsp.nodes);
4115         memset(&r_svbsp, 0, sizeof (r_svbsp));
4116         R_FreeTexturePool(&r_main_texturepool);
4117         loadingscreentexture = NULL;
4118         r_texture_blanknormalmap = NULL;
4119         r_texture_white = NULL;
4120         r_texture_grey128 = NULL;
4121         r_texture_black = NULL;
4122         r_texture_whitecube = NULL;
4123         r_texture_normalizationcube = NULL;
4124         r_texture_fogattenuation = NULL;
4125         r_texture_fogheighttexture = NULL;
4126         r_texture_gammaramps = NULL;
4127         r_texture_numcubemaps = 0;
4128         //r_texture_fogintensity = NULL;
4129         memset(&r_fb, 0, sizeof(r_fb));
4130         R_GLSL_Restart_f();
4131
4132         r_glsl_permutation = NULL;
4133         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4134         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4135         glslshaderstring = NULL;
4136 #ifdef SUPPORTD3D
4137         r_hlsl_permutation = NULL;
4138         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4139         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4140 #endif
4141         hlslshaderstring = NULL;
4142 }
4143
4144 extern void CL_ParseEntityLump(char *entitystring);
4145 void gl_main_newmap(void)
4146 {
4147         // FIXME: move this code to client
4148         char *entities, entname[MAX_QPATH];
4149         if (r_qwskincache)
4150                 Mem_Free(r_qwskincache);
4151         r_qwskincache = NULL;
4152         r_qwskincache_size = 0;
4153         if (cl.worldmodel)
4154         {
4155                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4156                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4157                 {
4158                         CL_ParseEntityLump(entities);
4159                         Mem_Free(entities);
4160                         return;
4161                 }
4162                 if (cl.worldmodel->brush.entities)
4163                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4164         }
4165         R_Main_FreeViewCache();
4166
4167         R_FrameData_Reset();
4168 }
4169
4170 void GL_Main_Init(void)
4171 {
4172         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4173
4174         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4175         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4176         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4177         if (gamemode == GAME_NEHAHRA)
4178         {
4179                 Cvar_RegisterVariable (&gl_fogenable);
4180                 Cvar_RegisterVariable (&gl_fogdensity);
4181                 Cvar_RegisterVariable (&gl_fogred);
4182                 Cvar_RegisterVariable (&gl_foggreen);
4183                 Cvar_RegisterVariable (&gl_fogblue);
4184                 Cvar_RegisterVariable (&gl_fogstart);
4185                 Cvar_RegisterVariable (&gl_fogend);
4186                 Cvar_RegisterVariable (&gl_skyclip);
4187         }
4188         Cvar_RegisterVariable(&r_motionblur);
4189         Cvar_RegisterVariable(&r_damageblur);
4190         Cvar_RegisterVariable(&r_motionblur_averaging);
4191         Cvar_RegisterVariable(&r_motionblur_randomize);
4192         Cvar_RegisterVariable(&r_motionblur_minblur);
4193         Cvar_RegisterVariable(&r_motionblur_maxblur);
4194         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4195         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4196         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4197         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4198         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4199         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4200         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4201         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4202         Cvar_RegisterVariable(&r_equalize_entities_by);
4203         Cvar_RegisterVariable(&r_equalize_entities_to);
4204         Cvar_RegisterVariable(&r_depthfirst);
4205         Cvar_RegisterVariable(&r_useinfinitefarclip);
4206         Cvar_RegisterVariable(&r_farclip_base);
4207         Cvar_RegisterVariable(&r_farclip_world);
4208         Cvar_RegisterVariable(&r_nearclip);
4209         Cvar_RegisterVariable(&r_deformvertexes);
4210         Cvar_RegisterVariable(&r_transparent);
4211         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4212         Cvar_RegisterVariable(&r_showoverdraw);
4213         Cvar_RegisterVariable(&r_showbboxes);
4214         Cvar_RegisterVariable(&r_showsurfaces);
4215         Cvar_RegisterVariable(&r_showtris);
4216         Cvar_RegisterVariable(&r_shownormals);
4217         Cvar_RegisterVariable(&r_showlighting);
4218         Cvar_RegisterVariable(&r_showshadowvolumes);
4219         Cvar_RegisterVariable(&r_showcollisionbrushes);
4220         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4221         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4222         Cvar_RegisterVariable(&r_showdisabledepthtest);
4223         Cvar_RegisterVariable(&r_drawportals);
4224         Cvar_RegisterVariable(&r_drawentities);
4225         Cvar_RegisterVariable(&r_draw2d);
4226         Cvar_RegisterVariable(&r_drawworld);
4227         Cvar_RegisterVariable(&r_cullentities_trace);
4228         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4229         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4230         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4231         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4232         Cvar_RegisterVariable(&r_sortentities);
4233         Cvar_RegisterVariable(&r_drawviewmodel);
4234         Cvar_RegisterVariable(&r_drawexteriormodel);
4235         Cvar_RegisterVariable(&r_speeds);
4236         Cvar_RegisterVariable(&r_fullbrights);
4237         Cvar_RegisterVariable(&r_wateralpha);
4238         Cvar_RegisterVariable(&r_dynamic);
4239         Cvar_RegisterVariable(&r_fakelight);
4240         Cvar_RegisterVariable(&r_fakelight_intensity);
4241         Cvar_RegisterVariable(&r_fullbright);
4242         Cvar_RegisterVariable(&r_shadows);
4243         Cvar_RegisterVariable(&r_shadows_darken);
4244         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4245         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4246         Cvar_RegisterVariable(&r_shadows_throwdistance);
4247         Cvar_RegisterVariable(&r_shadows_throwdirection);
4248         Cvar_RegisterVariable(&r_shadows_focus);
4249         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4250         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4251         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4252         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4253         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4254         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4255         Cvar_RegisterVariable(&r_fog_exp2);
4256         Cvar_RegisterVariable(&r_fog_clear);
4257         Cvar_RegisterVariable(&r_drawfog);
4258         Cvar_RegisterVariable(&r_transparentdepthmasking);
4259         Cvar_RegisterVariable(&r_transparent_sortmindist);
4260         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4261         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4262         Cvar_RegisterVariable(&r_texture_dds_load);
4263         Cvar_RegisterVariable(&r_texture_dds_save);
4264         Cvar_RegisterVariable(&r_textureunits);
4265         Cvar_RegisterVariable(&gl_combine);
4266         Cvar_RegisterVariable(&r_viewfbo);
4267         Cvar_RegisterVariable(&r_viewscale);
4268         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4271         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4272         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4273         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4274         Cvar_RegisterVariable(&r_glsl);
4275         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4276         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4281         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4282         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4283         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4284         Cvar_RegisterVariable(&r_glsl_postprocess);
4285         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4290         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4291         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4292         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4293
4294         Cvar_RegisterVariable(&r_water);
4295         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4296         Cvar_RegisterVariable(&r_water_clippingplanebias);
4297         Cvar_RegisterVariable(&r_water_refractdistort);
4298         Cvar_RegisterVariable(&r_water_reflectdistort);
4299         Cvar_RegisterVariable(&r_water_scissormode);
4300         Cvar_RegisterVariable(&r_water_lowquality);
4301         Cvar_RegisterVariable(&r_water_hideplayer);
4302         Cvar_RegisterVariable(&r_water_fbo);
4303
4304         Cvar_RegisterVariable(&r_lerpsprites);
4305         Cvar_RegisterVariable(&r_lerpmodels);
4306         Cvar_RegisterVariable(&r_lerplightstyles);
4307         Cvar_RegisterVariable(&r_waterscroll);
4308         Cvar_RegisterVariable(&r_bloom);
4309         Cvar_RegisterVariable(&r_bloom_colorscale);
4310         Cvar_RegisterVariable(&r_bloom_brighten);
4311         Cvar_RegisterVariable(&r_bloom_blur);
4312         Cvar_RegisterVariable(&r_bloom_resolution);
4313         Cvar_RegisterVariable(&r_bloom_colorexponent);
4314         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4315         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4316         Cvar_RegisterVariable(&r_hdr_glowintensity);
4317         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4318         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4321         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4322         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4323         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4324         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4325         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4326         Cvar_RegisterVariable(&developer_texturelogging);
4327         Cvar_RegisterVariable(&gl_lightmaps);
4328         Cvar_RegisterVariable(&r_test);
4329         Cvar_RegisterVariable(&r_glsl_saturation);
4330         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4331         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4332         Cvar_RegisterVariable(&r_framedatasize);
4333         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4334                 Cvar_SetValue("r_fullbrights", 0);
4335         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4336 }
4337
4338 extern void R_Textures_Init(void);
4339 extern void GL_Draw_Init(void);
4340 extern void GL_Main_Init(void);
4341 extern void R_Shadow_Init(void);
4342 extern void R_Sky_Init(void);
4343 extern void GL_Surf_Init(void);
4344 extern void R_Particles_Init(void);
4345 extern void R_Explosion_Init(void);
4346 extern void gl_backend_init(void);
4347 extern void Sbar_Init(void);
4348 extern void R_LightningBeams_Init(void);
4349 extern void Mod_RenderInit(void);
4350 extern void Font_Init(void);
4351
4352 void Render_Init(void)
4353 {
4354         gl_backend_init();
4355         R_Textures_Init();
4356         GL_Main_Init();
4357         Font_Init();
4358         GL_Draw_Init();
4359         R_Shadow_Init();
4360         R_Sky_Init();
4361         GL_Surf_Init();
4362         Sbar_Init();
4363         R_Particles_Init();
4364         R_Explosion_Init();
4365         R_LightningBeams_Init();
4366         Mod_RenderInit();
4367 }
4368
4369 /*
4370 ===============
4371 GL_Init
4372 ===============
4373 */
4374 #ifndef USE_GLES2
4375 extern char *ENGINE_EXTENSIONS;
4376 void GL_Init (void)
4377 {
4378         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4379         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4380         gl_version = (const char *)qglGetString(GL_VERSION);
4381         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4382
4383         if (!gl_extensions)
4384                 gl_extensions = "";
4385         if (!gl_platformextensions)
4386                 gl_platformextensions = "";
4387
4388         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4389         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4390         Con_Printf("GL_VERSION: %s\n", gl_version);
4391         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4392         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4393
4394         VID_CheckExtensions();
4395
4396         // LordHavoc: report supported extensions
4397         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4398
4399         // clear to black (loading plaque will be seen over this)
4400         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4401 }
4402 #endif
4403
4404 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4405 {
4406         int i;
4407         mplane_t *p;
4408         if (r_trippy.integer)
4409                 return false;
4410         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4411         {
4412                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4413                 if (i == 4)
4414                         continue;
4415                 p = r_refdef.view.frustum + i;
4416                 switch(p->signbits)
4417                 {
4418                 default:
4419                 case 0:
4420                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 1:
4424                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 2:
4428                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 3:
4432                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 4:
4436                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 5:
4440                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 6:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 7:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 }
4452         }
4453         return false;
4454 }
4455
4456 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4457 {
4458         int i;
4459         const mplane_t *p;
4460         if (r_trippy.integer)
4461                 return false;
4462         for (i = 0;i < numplanes;i++)
4463         {
4464                 p = planes + i;
4465                 switch(p->signbits)
4466                 {
4467                 default:
4468                 case 0:
4469                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 1:
4473                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 case 2:
4477                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4478                                 return true;
4479                         break;
4480                 case 3:
4481                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4482                                 return true;
4483                         break;
4484                 case 4:
4485                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4486                                 return true;
4487                         break;
4488                 case 5:
4489                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4490                                 return true;
4491                         break;
4492                 case 6:
4493                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4494                                 return true;
4495                         break;
4496                 case 7:
4497                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4498                                 return true;
4499                         break;
4500                 }
4501         }
4502         return false;
4503 }
4504
4505 //==================================================================================
4506
4507 // LordHavoc: this stores temporary data used within the same frame
4508
4509 typedef struct r_framedata_mem_s
4510 {
4511         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4512         size_t size; // how much usable space
4513         size_t current; // how much space in use
4514         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4515         size_t wantedsize; // how much space was allocated
4516         unsigned char *data; // start of real data (16byte aligned)
4517 }
4518 r_framedata_mem_t;
4519
4520 static r_framedata_mem_t *r_framedata_mem;
4521
4522 void R_FrameData_Reset(void)
4523 {
4524         while (r_framedata_mem)
4525         {
4526                 r_framedata_mem_t *next = r_framedata_mem->purge;
4527                 Mem_Free(r_framedata_mem);
4528                 r_framedata_mem = next;
4529         }
4530 }
4531
4532 void R_FrameData_Resize(void)
4533 {
4534         size_t wantedsize;
4535         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4536         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4537         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4538         {
4539                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4540                 newmem->wantedsize = wantedsize;
4541                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4542                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4543                 newmem->current = 0;
4544                 newmem->mark = 0;
4545                 newmem->purge = r_framedata_mem;
4546                 r_framedata_mem = newmem;
4547         }
4548 }
4549
4550 void R_FrameData_NewFrame(void)
4551 {
4552         R_FrameData_Resize();
4553         if (!r_framedata_mem)
4554                 return;
4555         // if we ran out of space on the last frame, free the old memory now
4556         while (r_framedata_mem->purge)
4557         {
4558                 // repeatedly remove the second item in the list, leaving only head
4559                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4560                 Mem_Free(r_framedata_mem->purge);
4561                 r_framedata_mem->purge = next;
4562         }
4563         // reset the current mem pointer
4564         r_framedata_mem->current = 0;
4565         r_framedata_mem->mark = 0;
4566 }
4567
4568 void *R_FrameData_Alloc(size_t size)
4569 {
4570         void *data;
4571
4572         // align to 16 byte boundary - the data pointer is already aligned, so we
4573         // only need to ensure the size of every allocation is also aligned
4574         size = (size + 15) & ~15;
4575
4576         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4577         {
4578                 // emergency - we ran out of space, allocate more memory
4579                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4580                 R_FrameData_Resize();
4581         }
4582
4583         data = r_framedata_mem->data + r_framedata_mem->current;
4584         r_framedata_mem->current += size;
4585
4586         // count the usage for stats
4587         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4588         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4589
4590         return (void *)data;
4591 }
4592
4593 void *R_FrameData_Store(size_t size, void *data)
4594 {
4595         void *d = R_FrameData_Alloc(size);
4596         if (d && data)
4597                 memcpy(d, data, size);
4598         return d;
4599 }
4600
4601 void R_FrameData_SetMark(void)
4602 {
4603         if (!r_framedata_mem)
4604                 return;
4605         r_framedata_mem->mark = r_framedata_mem->current;
4606 }
4607
4608 void R_FrameData_ReturnToMark(void)
4609 {
4610         if (!r_framedata_mem)
4611                 return;
4612         r_framedata_mem->current = r_framedata_mem->mark;
4613 }
4614
4615 //==================================================================================
4616
4617 // LordHavoc: animcache originally written by Echon, rewritten since then
4618
4619 /**
4620  * Animation cache prevents re-generating mesh data for an animated model
4621  * multiple times in one frame for lighting, shadowing, reflections, etc.
4622  */
4623
4624 void R_AnimCache_Free(void)
4625 {
4626 }
4627
4628 void R_AnimCache_ClearCache(void)
4629 {
4630         int i;
4631         entity_render_t *ent;
4632
4633         for (i = 0;i < r_refdef.scene.numentities;i++)
4634         {
4635                 ent = r_refdef.scene.entities[i];
4636                 ent->animcache_vertex3f = NULL;
4637                 ent->animcache_normal3f = NULL;
4638                 ent->animcache_svector3f = NULL;
4639                 ent->animcache_tvector3f = NULL;
4640                 ent->animcache_vertexmesh = NULL;
4641                 ent->animcache_vertex3fbuffer = NULL;
4642                 ent->animcache_vertexmeshbuffer = NULL;
4643         }
4644 }
4645
4646 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4647 {
4648         int i;
4649
4650         // check if we need the meshbuffers
4651         if (!vid.useinterleavedarrays)
4652                 return;
4653
4654         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4655                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4656         // TODO: upload vertex3f buffer?
4657         if (ent->animcache_vertexmesh)
4658         {
4659                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4660                 for (i = 0;i < numvertices;i++)
4661                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4662                 if (ent->animcache_svector3f)
4663                         for (i = 0;i < numvertices;i++)
4664                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4665                 if (ent->animcache_tvector3f)
4666                         for (i = 0;i < numvertices;i++)
4667                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4668                 if (ent->animcache_normal3f)
4669                         for (i = 0;i < numvertices;i++)
4670                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4671                 // TODO: upload vertexmeshbuffer?
4672         }
4673 }
4674
4675 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4676 {
4677         dp_model_t *model = ent->model;
4678         int numvertices;
4679         // see if it's already cached this frame
4680         if (ent->animcache_vertex3f)
4681         {
4682                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4683                 if (wantnormals || wanttangents)
4684                 {
4685                         if (ent->animcache_normal3f)
4686                                 wantnormals = false;
4687                         if (ent->animcache_svector3f)
4688                                 wanttangents = false;
4689                         if (wantnormals || wanttangents)
4690                         {
4691                                 numvertices = model->surfmesh.num_vertices;
4692                                 if (wantnormals)
4693                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4694                                 if (wanttangents)
4695                                 {
4696                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4697                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4698                                 }
4699                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4700                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4701                         }
4702                 }
4703         }
4704         else
4705         {
4706                 // see if this ent is worth caching
4707                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4708                         return false;
4709                 // get some memory for this entity and generate mesh data
4710                 numvertices = model->surfmesh.num_vertices;
4711                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4712                 if (wantnormals)
4713                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4714                 if (wanttangents)
4715                 {
4716                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4717                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4718                 }
4719                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4720                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4721         }
4722         return true;
4723 }
4724
4725 void R_AnimCache_CacheVisibleEntities(void)
4726 {
4727         int i;
4728         qboolean wantnormals = true;
4729         qboolean wanttangents = !r_showsurfaces.integer;
4730
4731         switch(vid.renderpath)
4732         {
4733         case RENDERPATH_GL20:
4734         case RENDERPATH_D3D9:
4735         case RENDERPATH_D3D10:
4736         case RENDERPATH_D3D11:
4737         case RENDERPATH_GLES2:
4738                 break;
4739         case RENDERPATH_GL11:
4740         case RENDERPATH_GL13:
4741         case RENDERPATH_GLES1:
4742                 wanttangents = false;
4743                 break;
4744         case RENDERPATH_SOFT:
4745                 break;
4746         }
4747
4748         if (r_shownormals.integer)
4749                 wanttangents = wantnormals = true;
4750
4751         // TODO: thread this
4752         // NOTE: R_PrepareRTLights() also caches entities
4753
4754         for (i = 0;i < r_refdef.scene.numentities;i++)
4755                 if (r_refdef.viewcache.entityvisible[i])
4756                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4757 }
4758
4759 //==================================================================================
4760
4761 extern cvar_t r_overheadsprites_pushback;
4762
4763 static void R_View_UpdateEntityLighting (void)
4764 {
4765         int i;
4766         entity_render_t *ent;
4767         vec3_t tempdiffusenormal, avg;
4768         vec_t f, fa, fd, fdd;
4769         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4770
4771         for (i = 0;i < r_refdef.scene.numentities;i++)
4772         {
4773                 ent = r_refdef.scene.entities[i];
4774
4775                 // skip unseen models and models that updated by CSQC
4776                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4777                         continue;
4778
4779                 // skip bsp models
4780                 if (ent->model && ent->model->brush.num_leafs)
4781                 {
4782                         // TODO: use modellight for r_ambient settings on world?
4783                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4784                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4785                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4786                         continue;
4787                 }
4788
4789                 // fetch the lighting from the worldmodel data
4790                 VectorClear(ent->modellight_ambient);
4791                 VectorClear(ent->modellight_diffuse);
4792                 VectorClear(tempdiffusenormal);
4793                 if (ent->flags & RENDER_LIGHT)
4794                 {
4795                         vec3_t org;
4796                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4797
4798                         // complete lightning for lit sprites
4799                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4800                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4801                         {
4802                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4803                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4804                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4805                         }
4806                         else
4807                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4808
4809                         if(ent->flags & RENDER_EQUALIZE)
4810                         {
4811                                 // first fix up ambient lighting...
4812                                 if(r_equalize_entities_minambient.value > 0)
4813                                 {
4814                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4815                                         if(fd > 0)
4816                                         {
4817                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4818                                                 if(fa < r_equalize_entities_minambient.value * fd)
4819                                                 {
4820                                                         // solve:
4821                                                         //   fa'/fd' = minambient
4822                                                         //   fa'+0.25*fd' = fa+0.25*fd
4823                                                         //   ...
4824                                                         //   fa' = fd' * minambient
4825                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4826                                                         //   ...
4827                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4828                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4829                                                         //   ...
4830                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4831                                                         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
4832                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4833                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4834                                                 }
4835                                         }
4836                                 }
4837
4838                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4839                                 {
4840                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4841                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4842                                         f = fa + 0.25 * fd;
4843                                         if(f > 0)
4844                                         {
4845                                                 // adjust brightness and saturation to target
4846                                                 avg[0] = avg[1] = avg[2] = fa / f;
4847                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4848                                                 avg[0] = avg[1] = avg[2] = fd / f;
4849                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4850                                         }
4851                                 }
4852                         }
4853                 }
4854                 else // highly rare
4855                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4856
4857                 // move the light direction into modelspace coordinates for lighting code
4858                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4859                 if(VectorLength2(ent->modellight_lightdir) == 0)
4860                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4861                 VectorNormalize(ent->modellight_lightdir);
4862         }
4863 }
4864
4865 #define MAX_LINEOFSIGHTTRACES 64
4866
4867 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4868 {
4869         int i;
4870         vec3_t boxmins, boxmaxs;
4871         vec3_t start;
4872         vec3_t end;
4873         dp_model_t *model = r_refdef.scene.worldmodel;
4874
4875         if (!model || !model->brush.TraceLineOfSight)
4876                 return true;
4877
4878         // expand the box a little
4879         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4880         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4881         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4882         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4883         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4884         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4885
4886         // return true if eye is inside enlarged box
4887         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4888                 return true;
4889
4890         // try center
4891         VectorCopy(eye, start);
4892         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4893         if (model->brush.TraceLineOfSight(model, start, end))
4894                 return true;
4895
4896         // try various random positions
4897         for (i = 0;i < numsamples;i++)
4898         {
4899                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4900                 if (model->brush.TraceLineOfSight(model, start, end))
4901                         return true;
4902         }
4903
4904         return false;
4905 }
4906
4907
4908 static void R_View_UpdateEntityVisible (void)
4909 {
4910         int i;
4911         int renderimask;
4912         int samples;
4913         entity_render_t *ent;
4914
4915         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4916                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4917                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4918                 :                                                          RENDER_EXTERIORMODEL;
4919         if (!r_drawviewmodel.integer)
4920                 renderimask |= RENDER_VIEWMODEL;
4921         if (!r_drawexteriormodel.integer)
4922                 renderimask |= RENDER_EXTERIORMODEL;
4923         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4924         {
4925                 // worldmodel can check visibility
4926                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4927                 for (i = 0;i < r_refdef.scene.numentities;i++)
4928                 {
4929                         ent = r_refdef.scene.entities[i];
4930                         if (!(ent->flags & renderimask))
4931                         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)))
4932                         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))
4933                                 r_refdef.viewcache.entityvisible[i] = true;
4934                 }
4935         }
4936         else
4937         {
4938                 // no worldmodel or it can't check visibility
4939                 for (i = 0;i < r_refdef.scene.numentities;i++)
4940                 {
4941                         ent = r_refdef.scene.entities[i];
4942                         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));
4943                 }
4944         }
4945         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4946                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4947         {
4948                 for (i = 0;i < r_refdef.scene.numentities;i++)
4949                 {
4950                         if (!r_refdef.viewcache.entityvisible[i])
4951                                 continue;
4952                         ent = r_refdef.scene.entities[i];
4953                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4954                         {
4955                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4956                                 if (samples < 0)
4957                                         continue; // temp entities do pvs only
4958                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4959                                         ent->last_trace_visibility = realtime;
4960                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4961                                         r_refdef.viewcache.entityvisible[i] = 0;
4962                         }
4963                 }
4964         }
4965 }
4966
4967 /// only used if skyrendermasked, and normally returns false
4968 int R_DrawBrushModelsSky (void)
4969 {
4970         int i, sky;
4971         entity_render_t *ent;
4972
4973         sky = false;
4974         for (i = 0;i < r_refdef.scene.numentities;i++)
4975         {
4976                 if (!r_refdef.viewcache.entityvisible[i])
4977                         continue;
4978                 ent = r_refdef.scene.entities[i];
4979                 if (!ent->model || !ent->model->DrawSky)
4980                         continue;
4981                 ent->model->DrawSky(ent);
4982                 sky = true;
4983         }
4984         return sky;
4985 }
4986
4987 static void R_DrawNoModel(entity_render_t *ent);
4988 static void R_DrawModels(void)
4989 {
4990         int i;
4991         entity_render_t *ent;
4992
4993         for (i = 0;i < r_refdef.scene.numentities;i++)
4994         {
4995                 if (!r_refdef.viewcache.entityvisible[i])
4996                         continue;
4997                 ent = r_refdef.scene.entities[i];
4998                 r_refdef.stats.entities++;
4999                 /*
5000                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5001                 {
5002                         vec3_t f, l, u, o;
5003                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5004                         Con_Printf("R_DrawModels\n");
5005                         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]);
5006                         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);
5007                         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);
5008                 }
5009                 */
5010                 if (ent->model && ent->model->Draw != NULL)
5011                         ent->model->Draw(ent);
5012                 else
5013                         R_DrawNoModel(ent);
5014         }
5015 }
5016
5017 static void R_DrawModelsDepth(void)
5018 {
5019         int i;
5020         entity_render_t *ent;
5021
5022         for (i = 0;i < r_refdef.scene.numentities;i++)
5023         {
5024                 if (!r_refdef.viewcache.entityvisible[i])
5025                         continue;
5026                 ent = r_refdef.scene.entities[i];
5027                 if (ent->model && ent->model->DrawDepth != NULL)
5028                         ent->model->DrawDepth(ent);
5029         }
5030 }
5031
5032 static void R_DrawModelsDebug(void)
5033 {
5034         int i;
5035         entity_render_t *ent;
5036
5037         for (i = 0;i < r_refdef.scene.numentities;i++)
5038         {
5039                 if (!r_refdef.viewcache.entityvisible[i])
5040                         continue;
5041                 ent = r_refdef.scene.entities[i];
5042                 if (ent->model && ent->model->DrawDebug != NULL)
5043                         ent->model->DrawDebug(ent);
5044         }
5045 }
5046
5047 static void R_DrawModelsAddWaterPlanes(void)
5048 {
5049         int i;
5050         entity_render_t *ent;
5051
5052         for (i = 0;i < r_refdef.scene.numentities;i++)
5053         {
5054                 if (!r_refdef.viewcache.entityvisible[i])
5055                         continue;
5056                 ent = r_refdef.scene.entities[i];
5057                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5058                         ent->model->DrawAddWaterPlanes(ent);
5059         }
5060 }
5061
5062 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}};
5063
5064 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5065 {
5066         if (r_hdr_irisadaptation.integer)
5067         {
5068                 vec3_t p;
5069                 vec3_t ambient;
5070                 vec3_t diffuse;
5071                 vec3_t diffusenormal;
5072                 vec3_t forward;
5073                 vec_t brightness = 0.0f;
5074                 vec_t goal;
5075                 vec_t current;
5076                 vec_t d;
5077                 int c;
5078                 VectorCopy(r_refdef.view.forward, forward);
5079                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5080                 {
5081                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5082                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5083                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5084                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5085                         d = DotProduct(forward, diffusenormal);
5086                         brightness += VectorLength(ambient);
5087                         if (d > 0)
5088                                 brightness += d * VectorLength(diffuse);
5089                 }
5090                 brightness *= 1.0f / c;
5091                 brightness += 0.00001f; // make sure it's never zero
5092                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5093                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5094                 current = r_hdr_irisadaptation_value.value;
5095                 if (current < goal)
5096                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5097                 else if (current > goal)
5098                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5099                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5100                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5101         }
5102         else if (r_hdr_irisadaptation_value.value != 1.0f)
5103                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5104 }
5105
5106 static void R_View_SetFrustum(const int *scissor)
5107 {
5108         int i;
5109         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5110         vec3_t forward, left, up, origin, v;
5111
5112         if(scissor)
5113         {
5114                 // flipped x coordinates (because x points left here)
5115                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5116                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5117
5118                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5119                 switch(vid.renderpath)
5120                 {
5121                         case RENDERPATH_D3D9:
5122                         case RENDERPATH_D3D10:
5123                         case RENDERPATH_D3D11:
5124                                 // non-flipped y coordinates
5125                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5126                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5127                                 break;
5128                         case RENDERPATH_SOFT:
5129                         case RENDERPATH_GL11:
5130                         case RENDERPATH_GL13:
5131                         case RENDERPATH_GL20:
5132                         case RENDERPATH_GLES1:
5133                         case RENDERPATH_GLES2:
5134                                 // non-flipped y coordinates
5135                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5136                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5137                                 break;
5138                 }
5139         }
5140
5141         // we can't trust r_refdef.view.forward and friends in reflected scenes
5142         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5143
5144 #if 0
5145         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5146         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5147         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5148         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5149         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5150         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5151         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5152         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5153         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5154         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5155         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5156         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5157 #endif
5158
5159 #if 0
5160         zNear = r_refdef.nearclip;
5161         nudge = 1.0 - 1.0 / (1<<23);
5162         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5163         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5164         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5165         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5166         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5167         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5168         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5169         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5170 #endif
5171
5172
5173
5174 #if 0
5175         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5176         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5177         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5178         r_refdef.view.frustum[0].dist = m[15] - m[12];
5179
5180         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5181         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5182         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5183         r_refdef.view.frustum[1].dist = m[15] + m[12];
5184
5185         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5186         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5187         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5188         r_refdef.view.frustum[2].dist = m[15] - m[13];
5189
5190         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5191         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5192         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5193         r_refdef.view.frustum[3].dist = m[15] + m[13];
5194
5195         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5196         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5197         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5198         r_refdef.view.frustum[4].dist = m[15] - m[14];
5199
5200         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5201         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5202         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5203         r_refdef.view.frustum[5].dist = m[15] + m[14];
5204 #endif
5205
5206         if (r_refdef.view.useperspective)
5207         {
5208                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5209                 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]);
5210                 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]);
5211                 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]);
5212                 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]);
5213
5214                 // then the normals from the corners relative to origin
5215                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5216                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5217                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5218                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5219
5220                 // in a NORMAL view, forward cross left == up
5221                 // in a REFLECTED view, forward cross left == down
5222                 // so our cross products above need to be adjusted for a left handed coordinate system
5223                 CrossProduct(forward, left, v);
5224                 if(DotProduct(v, up) < 0)
5225                 {
5226                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5227                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5228                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5229                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5230                 }
5231
5232                 // Leaving those out was a mistake, those were in the old code, and they
5233                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5234                 // I couldn't reproduce it after adding those normalizations. --blub
5235                 VectorNormalize(r_refdef.view.frustum[0].normal);
5236                 VectorNormalize(r_refdef.view.frustum[1].normal);
5237                 VectorNormalize(r_refdef.view.frustum[2].normal);
5238                 VectorNormalize(r_refdef.view.frustum[3].normal);
5239
5240                 // make the corners absolute
5241                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5242                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5243                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5244                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5245
5246                 // one more normal
5247                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5248
5249                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5250                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5251                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5252                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5253                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5254         }
5255         else
5256         {
5257                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5258                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5259                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5260                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5261                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5262                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5263                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5264                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5265                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5266                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5267         }
5268         r_refdef.view.numfrustumplanes = 5;
5269
5270         if (r_refdef.view.useclipplane)
5271         {
5272                 r_refdef.view.numfrustumplanes = 6;
5273                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5274         }
5275
5276         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5277                 PlaneClassify(r_refdef.view.frustum + i);
5278
5279         // LordHavoc: note to all quake engine coders, Quake had a special case
5280         // for 90 degrees which assumed a square view (wrong), so I removed it,
5281         // Quake2 has it disabled as well.
5282
5283         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5284         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5285         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5286         //PlaneClassify(&frustum[0]);
5287
5288         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5289         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5290         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5291         //PlaneClassify(&frustum[1]);
5292
5293         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5294         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5295         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5296         //PlaneClassify(&frustum[2]);
5297
5298         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5299         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5300         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5301         //PlaneClassify(&frustum[3]);
5302
5303         // nearclip plane
5304         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5305         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5306         //PlaneClassify(&frustum[4]);
5307 }
5308
5309 void R_View_UpdateWithScissor(const int *myscissor)
5310 {
5311         R_Main_ResizeViewCache();
5312         R_View_SetFrustum(myscissor);
5313         R_View_WorldVisibility(r_refdef.view.useclipplane);
5314         R_View_UpdateEntityVisible();
5315         R_View_UpdateEntityLighting();
5316         R_AnimCache_CacheVisibleEntities();
5317 }
5318
5319 void R_View_Update(void)
5320 {
5321         R_Main_ResizeViewCache();
5322         R_View_SetFrustum(NULL);
5323         R_View_WorldVisibility(r_refdef.view.useclipplane);
5324         R_View_UpdateEntityVisible();
5325         R_View_UpdateEntityLighting();
5326         R_AnimCache_CacheVisibleEntities();
5327 }
5328
5329 float viewscalefpsadjusted = 1.0f;
5330
5331 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5332 {
5333         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5334         scale = bound(0.03125f, scale, 1.0f);
5335         *outwidth = (int)ceil(width * scale);
5336         *outheight = (int)ceil(height * scale);
5337 }
5338
5339 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5340 {
5341         const float *customclipplane = NULL;
5342         float plane[4];
5343         int scaledwidth, scaledheight;
5344         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5345         {
5346                 // LordHavoc: couldn't figure out how to make this approach the
5347                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5348                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5349                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5350                         dist = r_refdef.view.clipplane.dist;
5351                 plane[0] = r_refdef.view.clipplane.normal[0];
5352                 plane[1] = r_refdef.view.clipplane.normal[1];
5353                 plane[2] = r_refdef.view.clipplane.normal[2];
5354                 plane[3] = -dist;
5355                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5356         }
5357
5358         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5359         if (!r_refdef.view.useperspective)
5360                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - 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);
5361         else if (vid.stencil && r_useinfinitefarclip.integer)
5362                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5363         else
5364                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5365         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5366         R_SetViewport(&r_refdef.view.viewport);
5367         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5368         {
5369                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5370                 float screenplane[4];
5371                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5372                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5373                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5374                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5375                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5376         }
5377 }
5378
5379 void R_EntityMatrix(const matrix4x4_t *matrix)
5380 {
5381         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5382         {
5383                 gl_modelmatrixchanged = false;
5384                 gl_modelmatrix = *matrix;
5385                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5386                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5387                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5388                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5389                 CHECKGLERROR
5390                 switch(vid.renderpath)
5391                 {
5392                 case RENDERPATH_D3D9:
5393 #ifdef SUPPORTD3D
5394                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5395                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5396 #endif
5397                         break;
5398                 case RENDERPATH_D3D10:
5399                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5400                         break;
5401                 case RENDERPATH_D3D11:
5402                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5403                         break;
5404                 case RENDERPATH_GL11:
5405                 case RENDERPATH_GL13:
5406                 case RENDERPATH_GLES1:
5407                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5408                         break;
5409                 case RENDERPATH_SOFT:
5410                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5411                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5412                         break;
5413                 case RENDERPATH_GL20:
5414                 case RENDERPATH_GLES2:
5415                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5416                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5417                         break;
5418                 }
5419         }
5420 }
5421
5422 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5423 {
5424         r_viewport_t viewport;
5425         DrawQ_Finish();
5426
5427         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5428         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, 1, 1, -10, 100, NULL);
5429         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5430         R_SetViewport(&viewport);
5431         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5432         GL_Color(1, 1, 1, 1);
5433         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5434         GL_BlendFunc(GL_ONE, GL_ZERO);
5435         GL_ScissorTest(false);
5436         GL_DepthMask(false);
5437         GL_DepthRange(0, 1);
5438         GL_DepthTest(false);
5439         GL_DepthFunc(GL_LEQUAL);
5440         R_EntityMatrix(&identitymatrix);
5441         R_Mesh_ResetTextureState();
5442         GL_PolygonOffset(0, 0);
5443         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5444         switch(vid.renderpath)
5445         {
5446         case RENDERPATH_GL11:
5447         case RENDERPATH_GL13:
5448         case RENDERPATH_GL20:
5449         case RENDERPATH_GLES1:
5450         case RENDERPATH_GLES2:
5451                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5452                 break;
5453         case RENDERPATH_D3D9:
5454         case RENDERPATH_D3D10:
5455         case RENDERPATH_D3D11:
5456         case RENDERPATH_SOFT:
5457                 break;
5458         }
5459         GL_CullFace(GL_NONE);
5460 }
5461
5462 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5463 {
5464         DrawQ_Finish();
5465
5466         R_SetupView(true, fbo, depthtexture, colortexture);
5467         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5468         GL_Color(1, 1, 1, 1);
5469         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5470         GL_BlendFunc(GL_ONE, GL_ZERO);
5471         GL_ScissorTest(true);
5472         GL_DepthMask(true);
5473         GL_DepthRange(0, 1);
5474         GL_DepthTest(true);
5475         GL_DepthFunc(GL_LEQUAL);
5476         R_EntityMatrix(&identitymatrix);
5477         R_Mesh_ResetTextureState();
5478         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5479         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5480         switch(vid.renderpath)
5481         {
5482         case RENDERPATH_GL11:
5483         case RENDERPATH_GL13:
5484         case RENDERPATH_GL20:
5485         case RENDERPATH_GLES1:
5486         case RENDERPATH_GLES2:
5487                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5488                 break;
5489         case RENDERPATH_D3D9:
5490         case RENDERPATH_D3D10:
5491         case RENDERPATH_D3D11:
5492         case RENDERPATH_SOFT:
5493                 break;
5494         }
5495         GL_CullFace(r_refdef.view.cullface_back);
5496 }
5497
5498 /*
5499 ================
5500 R_RenderView_UpdateViewVectors
5501 ================
5502 */
5503 static void R_RenderView_UpdateViewVectors(void)
5504 {
5505         // break apart the view matrix into vectors for various purposes
5506         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5507         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5508         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5509         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5510         // make an inverted copy of the view matrix for tracking sprites
5511         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5512 }
5513
5514 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5515 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5516
5517 static void R_Water_StartFrame(void)
5518 {
5519         int i;
5520         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5521         r_waterstate_waterplane_t *p;
5522
5523         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5524                 return;
5525
5526         switch(vid.renderpath)
5527         {
5528         case RENDERPATH_GL20:
5529         case RENDERPATH_D3D9:
5530         case RENDERPATH_D3D10:
5531         case RENDERPATH_D3D11:
5532         case RENDERPATH_SOFT:
5533         case RENDERPATH_GLES2:
5534                 break;
5535         case RENDERPATH_GL11:
5536         case RENDERPATH_GL13:
5537         case RENDERPATH_GLES1:
5538                 return;
5539         }
5540
5541         // set waterwidth and waterheight to the water resolution that will be
5542         // used (often less than the screen resolution for faster rendering)
5543         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5544
5545         // calculate desired texture sizes
5546         // can't use water if the card does not support the texture size
5547         if (!r_water.integer || r_showsurfaces.integer)
5548                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5549         else if (vid.support.arb_texture_non_power_of_two)
5550         {
5551                 texturewidth = waterwidth;
5552                 textureheight = waterheight;
5553                 camerawidth = waterwidth;
5554                 cameraheight = waterheight;
5555         }
5556         else
5557         {
5558                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5559                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5560                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5561                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5562         }
5563
5564         // allocate textures as needed
5565         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight)
5566         {
5567                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5568                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5569                 {
5570                         if (p->texture_refraction)
5571                                 R_FreeTexture(p->texture_refraction);
5572                         p->texture_refraction = NULL;
5573                         if (p->fbo_refraction)
5574                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5575                         p->fbo_refraction = 0;
5576                         if (p->texture_reflection)
5577                                 R_FreeTexture(p->texture_reflection);
5578                         p->texture_reflection = NULL;
5579                         if (p->fbo_reflection)
5580                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5581                         p->fbo_reflection = 0;
5582                         if (p->texture_camera)
5583                                 R_FreeTexture(p->texture_camera);
5584                         p->texture_camera = NULL;
5585                         if (p->fbo_camera)
5586                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5587                         p->fbo_camera = 0;
5588                 }
5589                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5590                 r_fb.water.texturewidth = texturewidth;
5591                 r_fb.water.textureheight = textureheight;
5592                 r_fb.water.camerawidth = camerawidth;
5593                 r_fb.water.cameraheight = cameraheight;
5594         }
5595
5596         if (r_fb.water.texturewidth)
5597         {
5598                 int scaledwidth, scaledheight;
5599
5600                 r_fb.water.enabled = true;
5601
5602                 // water resolution is usually reduced
5603                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5604                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5605                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5606
5607                 // set up variables that will be used in shader setup
5608                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5609                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5610                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5611                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5612         }
5613
5614         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5615         r_fb.water.numwaterplanes = 0;
5616 }
5617
5618 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5619 {
5620         int planeindex, bestplaneindex, vertexindex;
5621         vec3_t mins, maxs, normal, center, v, n;
5622         vec_t planescore, bestplanescore;
5623         mplane_t plane;
5624         r_waterstate_waterplane_t *p;
5625         texture_t *t = R_GetCurrentTexture(surface->texture);
5626
5627         rsurface.texture = t;
5628         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5629         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5630         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5631                 return;
5632         // average the vertex normals, find the surface bounds (after deformvertexes)
5633         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5634         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5635         VectorCopy(n, normal);
5636         VectorCopy(v, mins);
5637         VectorCopy(v, maxs);
5638         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5639         {
5640                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5641                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5642                 VectorAdd(normal, n, normal);
5643                 mins[0] = min(mins[0], v[0]);
5644                 mins[1] = min(mins[1], v[1]);
5645                 mins[2] = min(mins[2], v[2]);
5646                 maxs[0] = max(maxs[0], v[0]);
5647                 maxs[1] = max(maxs[1], v[1]);
5648                 maxs[2] = max(maxs[2], v[2]);
5649         }
5650         VectorNormalize(normal);
5651         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5652
5653         VectorCopy(normal, plane.normal);
5654         VectorNormalize(plane.normal);
5655         plane.dist = DotProduct(center, plane.normal);
5656         PlaneClassify(&plane);
5657         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5658         {
5659                 // skip backfaces (except if nocullface is set)
5660 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5661 //                      return;
5662                 VectorNegate(plane.normal, plane.normal);
5663                 plane.dist *= -1;
5664                 PlaneClassify(&plane);
5665         }
5666
5667
5668         // find a matching plane if there is one
5669         bestplaneindex = -1;
5670         bestplanescore = 1048576.0f;
5671         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5672         {
5673                 if(p->camera_entity == t->camera_entity)
5674                 {
5675                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5676                         if (bestplaneindex < 0 || bestplanescore > planescore)
5677                         {
5678                                 bestplaneindex = planeindex;
5679                                 bestplanescore = planescore;
5680                         }
5681                 }
5682         }
5683         planeindex = bestplaneindex;
5684         p = r_fb.water.waterplanes + planeindex;
5685
5686         // if this surface does not fit any known plane rendered this frame, add one
5687         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5688         {
5689                 // store the new plane
5690                 planeindex = r_fb.water.numwaterplanes++;
5691                 p = r_fb.water.waterplanes + planeindex;
5692                 p->plane = plane;
5693                 // clear materialflags and pvs
5694                 p->materialflags = 0;
5695                 p->pvsvalid = false;
5696                 p->camera_entity = t->camera_entity;
5697                 VectorCopy(mins, p->mins);
5698                 VectorCopy(maxs, p->maxs);
5699         }
5700         else
5701         {
5702                 // merge mins/maxs when we're adding this surface to the plane
5703                 p->mins[0] = min(p->mins[0], mins[0]);
5704                 p->mins[1] = min(p->mins[1], mins[1]);
5705                 p->mins[2] = min(p->mins[2], mins[2]);
5706                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5707                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5708                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5709         }
5710         // merge this surface's materialflags into the waterplane
5711         p->materialflags |= t->currentmaterialflags;
5712         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5713         {
5714                 // merge this surface's PVS into the waterplane
5715                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5716                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5717                 {
5718                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5719                         p->pvsvalid = true;
5720                 }
5721         }
5722 }
5723
5724 extern cvar_t r_drawparticles;
5725 extern cvar_t r_drawdecals;
5726
5727 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5728 {
5729         int myscissor[4];
5730         r_refdef_view_t originalview;
5731         r_refdef_view_t myview;
5732         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;
5733         r_waterstate_waterplane_t *p;
5734         vec3_t visorigin;
5735
5736         originalview = r_refdef.view;
5737
5738         // lowquality hack, temporarily shut down some cvars and restore afterwards
5739         qualityreduction = r_water_lowquality.integer;
5740         if (qualityreduction > 0)
5741         {
5742                 if (qualityreduction >= 1)
5743                 {
5744                         old_r_shadows = r_shadows.integer;
5745                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5746                         old_r_dlight = r_shadow_realtime_dlight.integer;
5747                         Cvar_SetValueQuick(&r_shadows, 0);
5748                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5749                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5750                 }
5751                 if (qualityreduction >= 2)
5752                 {
5753                         old_r_dynamic = r_dynamic.integer;
5754                         old_r_particles = r_drawparticles.integer;
5755                         old_r_decals = r_drawdecals.integer;
5756                         Cvar_SetValueQuick(&r_dynamic, 0);
5757                         Cvar_SetValueQuick(&r_drawparticles, 0);
5758                         Cvar_SetValueQuick(&r_drawdecals, 0);
5759                 }
5760         }
5761
5762         // make sure enough textures are allocated
5763         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5764         {
5765                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5766                 {
5767                         if (!p->texture_refraction)
5768                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5769                         if (!p->texture_refraction)
5770                                 goto error;
5771                         if (r_water_fbo.integer >= 1 && vid.support.ext_framebuffer_object)
5772                         {
5773                                 if (r_fb.water.depthtexture == NULL)
5774                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5775                                 if (p->fbo_refraction == 0)
5776                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5777                         }
5778                 }
5779                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5780                 {
5781                         if (!p->texture_camera)
5782                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5783                         if (!p->texture_camera)
5784                                 goto error;
5785                         if (r_water_fbo.integer >= 1 && vid.support.ext_framebuffer_object)
5786                         {
5787                                 if (r_fb.water.depthtexture == NULL)
5788                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5789                                 if (p->fbo_camera == 0)
5790                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5791                         }
5792                 }
5793
5794                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5795                 {
5796                         if (!p->texture_reflection)
5797                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5798                         if (!p->texture_reflection)
5799                                 goto error;
5800                         if (r_water_fbo.integer >= 1 && vid.support.ext_framebuffer_object)
5801                         {
5802                                 if (r_fb.water.depthtexture == NULL)
5803                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5804                                 if (p->fbo_reflection == 0)
5805                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5806                         }
5807                 }
5808         }
5809
5810         // render views
5811         r_refdef.view = originalview;
5812         r_refdef.view.showdebug = false;
5813         r_refdef.view.width = r_fb.water.waterwidth;
5814         r_refdef.view.height = r_fb.water.waterheight;
5815         r_refdef.view.useclipplane = true;
5816         myview = r_refdef.view;
5817         r_fb.water.renderingscene = true;
5818         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5819         {
5820                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5821                 {
5822                         r_refdef.view = myview;
5823                         if(r_water_scissormode.integer)
5824                         {
5825                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5826                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5827                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5828                         }
5829
5830                         // render reflected scene and copy into texture
5831                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5832                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5833                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5834                         r_refdef.view.clipplane = p->plane;
5835                         // reverse the cullface settings for this render
5836                         r_refdef.view.cullface_front = GL_FRONT;
5837                         r_refdef.view.cullface_back = GL_BACK;
5838                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5839                         {
5840                                 r_refdef.view.usecustompvs = true;
5841                                 if (p->pvsvalid)
5842                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5843                                 else
5844                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5845                         }
5846
5847                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5848                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5849                         R_ClearScreen(r_refdef.fogenabled);
5850                         if(r_water_scissormode.integer & 2)
5851                                 R_View_UpdateWithScissor(myscissor);
5852                         else
5853                                 R_View_Update();
5854                         if(r_water_scissormode.integer & 1)
5855                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5856                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5857
5858                         if (!p->fbo_reflection)
5859                                 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);
5860                         r_fb.water.hideplayer = false;
5861                 }
5862
5863                 // render the normal view scene and copy into texture
5864                 // (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)
5865                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5866                 {
5867                         r_refdef.view = myview;
5868                         if(r_water_scissormode.integer)
5869                         {
5870                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5871                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5872                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5873                         }
5874
5875                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5876
5877                         r_refdef.view.clipplane = p->plane;
5878                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5879                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5880
5881                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5882                         {
5883                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5884                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5885                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5886                                 R_RenderView_UpdateViewVectors();
5887                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5888                                 {
5889                                         r_refdef.view.usecustompvs = true;
5890                                         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);
5891                                 }
5892                         }
5893
5894                         PlaneClassify(&r_refdef.view.clipplane);
5895
5896                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5897                         R_ClearScreen(r_refdef.fogenabled);
5898                         if(r_water_scissormode.integer & 2)
5899                                 R_View_UpdateWithScissor(myscissor);
5900                         else
5901                                 R_View_Update();
5902                         if(r_water_scissormode.integer & 1)
5903                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5904                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5905
5906                         if (!p->fbo_refraction)
5907                                 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);
5908                         r_fb.water.hideplayer = false;
5909                 }
5910                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5911                 {
5912                         r_refdef.view = myview;
5913
5914                         r_refdef.view.clipplane = p->plane;
5915                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5916                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5917
5918                         r_refdef.view.width = r_fb.water.camerawidth;
5919                         r_refdef.view.height = r_fb.water.cameraheight;
5920                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5921                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5922                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5923                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5924
5925                         if(p->camera_entity)
5926                         {
5927                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5928                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5929                         }
5930
5931                         // note: all of the view is used for displaying... so
5932                         // there is no use in scissoring
5933
5934                         // reverse the cullface settings for this render
5935                         r_refdef.view.cullface_front = GL_FRONT;
5936                         r_refdef.view.cullface_back = GL_BACK;
5937                         // also reverse the view matrix
5938                         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
5939                         R_RenderView_UpdateViewVectors();
5940                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5941                         {
5942                                 r_refdef.view.usecustompvs = true;
5943                                 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);
5944                         }
5945                         
5946                         // camera needs no clipplane
5947                         r_refdef.view.useclipplane = false;
5948
5949                         PlaneClassify(&r_refdef.view.clipplane);
5950
5951                         r_fb.water.hideplayer = false;
5952
5953                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5954                         R_ClearScreen(r_refdef.fogenabled);
5955                         R_View_Update();
5956                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5957
5958                         if (!p->fbo_camera)
5959                                 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);
5960                         r_fb.water.hideplayer = false;
5961                 }
5962
5963         }
5964         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5965         r_fb.water.renderingscene = false;
5966         r_refdef.view = originalview;
5967         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5968         if (!r_fb.water.depthtexture)
5969                 R_ClearScreen(r_refdef.fogenabled);
5970         R_View_Update();
5971         goto finish;
5972 error:
5973         r_refdef.view = originalview;
5974         r_fb.water.renderingscene = false;
5975         Cvar_SetValueQuick(&r_water, 0);
5976         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5977 finish:
5978         // lowquality hack, restore cvars
5979         if (qualityreduction > 0)
5980         {
5981                 if (qualityreduction >= 1)
5982                 {
5983                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5984                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5985                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5986                 }
5987                 if (qualityreduction >= 2)
5988                 {
5989                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5990                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5991                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5992                 }
5993         }
5994 }
5995
5996 void R_Bloom_StartFrame(void)
5997 {
5998         int i;
5999         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6000         int viewwidth, viewheight;
6001
6002         r_fb.textype = TEXTYPE_COLORBUFFER;
6003         switch (vid.renderpath)
6004         {
6005         case RENDERPATH_GL20:
6006         case RENDERPATH_GLES2:
6007                 if (vid.support.ext_framebuffer_object)
6008                 {
6009                         if (r_viewfbo.integer == 2) r_fb.textype = TEXTYPE_COLORBUFFER16F;
6010                         if (r_viewfbo.integer == 3) r_fb.textype = TEXTYPE_COLORBUFFER32F;
6011                 }
6012                 break;
6013         case RENDERPATH_GL11:
6014         case RENDERPATH_GL13:
6015         case RENDERPATH_GLES1:
6016         case RENDERPATH_D3D9:
6017         case RENDERPATH_D3D10:
6018         case RENDERPATH_D3D11:
6019         case RENDERPATH_SOFT:
6020                 break;
6021         }
6022
6023         if (r_viewscale_fpsscaling.integer)
6024         {
6025                 double actualframetime;
6026                 double targetframetime;
6027                 double adjust;
6028                 actualframetime = r_refdef.lastdrawscreentime;
6029                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6030                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6031                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6032                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6033                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6034                 viewscalefpsadjusted += adjust;
6035                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6036         }
6037         else
6038                 viewscalefpsadjusted = 1.0f;
6039
6040         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6041
6042         switch(vid.renderpath)
6043         {
6044         case RENDERPATH_GL20:
6045         case RENDERPATH_D3D9:
6046         case RENDERPATH_D3D10:
6047         case RENDERPATH_D3D11:
6048         case RENDERPATH_SOFT:
6049         case RENDERPATH_GLES2:
6050                 break;
6051         case RENDERPATH_GL11:
6052         case RENDERPATH_GL13:
6053         case RENDERPATH_GLES1:
6054                 return;
6055         }
6056
6057         // set bloomwidth and bloomheight to the bloom resolution that will be
6058         // used (often less than the screen resolution for faster rendering)
6059         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6060         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6061         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6062         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6063         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6064
6065         // calculate desired texture sizes
6066         if (vid.support.arb_texture_non_power_of_two)
6067         {
6068                 screentexturewidth = vid.width;
6069                 screentextureheight = vid.height;
6070                 bloomtexturewidth = r_fb.bloomwidth;
6071                 bloomtextureheight = r_fb.bloomheight;
6072         }
6073         else
6074         {
6075                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6076                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6077                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6078                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6079         }
6080
6081         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))
6082         {
6083                 Cvar_SetValueQuick(&r_bloom, 0);
6084                 Cvar_SetValueQuick(&r_motionblur, 0);
6085                 Cvar_SetValueQuick(&r_damageblur, 0);
6086         }
6087
6088         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
6089                 screentexturewidth = screentextureheight = 0;
6090         if (!r_bloom.integer)
6091                 bloomtexturewidth = bloomtextureheight = 0;
6092
6093         // allocate textures as needed
6094         if (r_fb.screentexturewidth != screentexturewidth
6095          || r_fb.screentextureheight != screentextureheight
6096          || r_fb.bloomtexturewidth != bloomtexturewidth
6097          || r_fb.bloomtextureheight != bloomtextureheight
6098          || r_fb.viewfbo != r_viewfbo.integer)
6099         {
6100                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6101                 {
6102                         if (r_fb.bloomtexture[i])
6103                                 R_FreeTexture(r_fb.bloomtexture[i]);
6104                         r_fb.bloomtexture[i] = NULL;
6105
6106                         if (r_fb.bloomfbo[i])
6107                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6108                         r_fb.bloomfbo[i] = 0;
6109                 }
6110
6111                 if (r_fb.fbo)
6112                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6113                 r_fb.fbo = 0;
6114
6115                 if (r_fb.colortexture)
6116                         R_FreeTexture(r_fb.colortexture);
6117                 r_fb.colortexture = NULL;
6118
6119                 if (r_fb.depthtexture)
6120                         R_FreeTexture(r_fb.depthtexture);
6121                 r_fb.depthtexture = NULL;
6122
6123                 if (r_fb.ghosttexture)
6124                         R_FreeTexture(r_fb.ghosttexture);
6125                 r_fb.ghosttexture = NULL;
6126
6127                 r_fb.screentexturewidth = screentexturewidth;
6128                 r_fb.screentextureheight = screentextureheight;
6129                 r_fb.bloomtexturewidth = bloomtexturewidth;
6130                 r_fb.bloomtextureheight = bloomtextureheight;
6131                 r_fb.viewfbo = r_viewfbo.integer;
6132
6133                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6134                 {
6135                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6136                                 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);
6137                         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);
6138                         if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6139                         {
6140                                 // FIXME: choose depth bits based on a cvar
6141                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
6142                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6143                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6144 #ifndef USE_GLES2
6145                                 // render depth into one texture and color into the other
6146                                 if (qglDrawBuffer)
6147                                 {
6148                                         int status;
6149                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6150                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6151                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6152                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6153                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6154                                 }
6155 #endif
6156                         }
6157                 }
6158
6159                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6160                 {
6161                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6162                         {
6163                                 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);
6164                                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6165                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6166                         }
6167                 }
6168         }
6169
6170         // bloom texture is a different resolution
6171         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6172         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6173         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6174         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6175         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6176
6177         // set up a texcoord array for the full resolution screen image
6178         // (we have to keep this around to copy back during final render)
6179         r_fb.screentexcoord2f[0] = 0;
6180         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6181         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6182         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6183         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6184         r_fb.screentexcoord2f[5] = 0;
6185         r_fb.screentexcoord2f[6] = 0;
6186         r_fb.screentexcoord2f[7] = 0;
6187
6188         // set up a texcoord array for the reduced resolution bloom image
6189         // (which will be additive blended over the screen image)
6190         r_fb.bloomtexcoord2f[0] = 0;
6191         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6192         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6193         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6194         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6195         r_fb.bloomtexcoord2f[5] = 0;
6196         r_fb.bloomtexcoord2f[6] = 0;
6197         r_fb.bloomtexcoord2f[7] = 0;
6198
6199         switch(vid.renderpath)
6200         {
6201         case RENDERPATH_GL11:
6202         case RENDERPATH_GL13:
6203         case RENDERPATH_GL20:
6204         case RENDERPATH_SOFT:
6205         case RENDERPATH_GLES1:
6206         case RENDERPATH_GLES2:
6207                 break;
6208         case RENDERPATH_D3D9:
6209         case RENDERPATH_D3D10:
6210         case RENDERPATH_D3D11:
6211                 {
6212                         int i;
6213                         for (i = 0;i < 4;i++)
6214                         {
6215                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6216                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6217                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6218                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6219                         }
6220                 }
6221                 break;
6222         }
6223
6224         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);
6225
6226         if (r_fb.fbo)
6227                 r_refdef.view.clear = true;
6228 }
6229
6230 void R_Bloom_MakeTexture(void)
6231 {
6232         int x, range, dir;
6233         float xoffset, yoffset, r, brighten;
6234         rtexture_t *intex;
6235         float colorscale = r_bloom_colorscale.value;
6236
6237         r_refdef.stats.bloom++;
6238
6239         if (!r_fb.fbo)
6240         {
6241                 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);
6242                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6243         }
6244
6245         // scale down screen texture to the bloom texture size
6246         CHECKGLERROR
6247         r_fb.bloomindex = 0;
6248         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6249         R_SetViewport(&r_fb.bloomviewport);
6250         GL_BlendFunc(GL_ONE, GL_ZERO);
6251         GL_Color(colorscale, colorscale, colorscale, 1);
6252         // 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...
6253         switch(vid.renderpath)
6254         {
6255         case RENDERPATH_GL11:
6256         case RENDERPATH_GL13:
6257         case RENDERPATH_GL20:
6258         case RENDERPATH_GLES1:
6259         case RENDERPATH_GLES2:
6260         case RENDERPATH_SOFT:
6261                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6262                 break;
6263         case RENDERPATH_D3D9:
6264         case RENDERPATH_D3D10:
6265         case RENDERPATH_D3D11:
6266                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6267                 break;
6268         }
6269         // TODO: do boxfilter scale-down in shader?
6270         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true);
6271         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6272         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6273
6274         // we now have a properly scaled bloom image
6275         if (!r_fb.bloomfbo[r_fb.bloomindex])
6276         {
6277                 // copy it into the bloom texture
6278                 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);
6279                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6280         }
6281
6282         // multiply bloom image by itself as many times as desired
6283         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6284         {
6285                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6286                 r_fb.bloomindex ^= 1;
6287                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6288                 x *= 2;
6289                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6290                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6291                 GL_Color(r,r,r,1);
6292                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6293                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true);
6294                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6295                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6296
6297                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6298                 {
6299                         // copy the darkened image to a texture
6300                         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);
6301                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6302                 }
6303         }
6304
6305         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6306         brighten = r_bloom_brighten.value;
6307         brighten = sqrt(brighten);
6308         if(range >= 1)
6309                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6310
6311         for (dir = 0;dir < 2;dir++)
6312         {
6313                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6314                 r_fb.bloomindex ^= 1;
6315                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6316                 // blend on at multiple vertical offsets to achieve a vertical blur
6317                 // TODO: do offset blends using GLSL
6318                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6319                 GL_BlendFunc(GL_ONE, GL_ZERO);
6320                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true);
6321                 for (x = -range;x <= range;x++)
6322                 {
6323                         if (!dir){xoffset = 0;yoffset = x;}
6324                         else {xoffset = x;yoffset = 0;}
6325                         xoffset /= (float)r_fb.bloomtexturewidth;
6326                         yoffset /= (float)r_fb.bloomtextureheight;
6327                         // compute a texcoord array with the specified x and y offset
6328                         r_fb.offsettexcoord2f[0] = xoffset+0;
6329                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6330                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6331                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6332                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6333                         r_fb.offsettexcoord2f[5] = yoffset+0;
6334                         r_fb.offsettexcoord2f[6] = xoffset+0;
6335                         r_fb.offsettexcoord2f[7] = yoffset+0;
6336                         // this r value looks like a 'dot' particle, fading sharply to
6337                         // black at the edges
6338                         // (probably not realistic but looks good enough)
6339                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6340                         //r = brighten/(range*2+1);
6341                         r = brighten / (range * 2 + 1);
6342                         if(range >= 1)
6343                                 r *= (1 - x*x/(float)(range*range));
6344                         GL_Color(r, r, r, 1);
6345                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6346                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6347                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6348                         GL_BlendFunc(GL_ONE, GL_ONE);
6349                 }
6350
6351                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6352                 {
6353                         // copy the vertically or horizontally blurred bloom view to a texture
6354                         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);
6355                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6356                 }
6357         }
6358 }
6359
6360 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6361 {
6362         unsigned int permutation;
6363         float uservecs[4][4];
6364
6365         switch (vid.renderpath)
6366         {
6367         case RENDERPATH_GL20:
6368         case RENDERPATH_D3D9:
6369         case RENDERPATH_D3D10:
6370         case RENDERPATH_D3D11:
6371         case RENDERPATH_SOFT:
6372         case RENDERPATH_GLES2:
6373                 permutation =
6374                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6375                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6376                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6377                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6378                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6379
6380                 if (r_fb.colortexture)
6381                 {
6382                         if (!r_fb.fbo)
6383                         {
6384                                 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);
6385                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6386                         }
6387
6388                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6389                         {
6390                                 // declare variables
6391                                 float blur_factor, blur_mouseaccel, blur_velocity;
6392                                 static float blur_average; 
6393                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6394
6395                                 // set a goal for the factoring
6396                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6397                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6398                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6399                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6400                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6401                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6402
6403                                 // from the goal, pick an averaged value between goal and last value
6404                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6405                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6406
6407                                 // enforce minimum amount of blur 
6408                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6409
6410                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6411
6412                                 // calculate values into a standard alpha
6413                                 cl.motionbluralpha = 1 - exp(-
6414                                                 (
6415                                                  (r_motionblur.value * blur_factor / 80)
6416                                                  +
6417                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6418                                                 )
6419                                                 /
6420                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6421                                           );
6422
6423                                 // randomization for the blur value to combat persistent ghosting
6424                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6425                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6426
6427                                 // apply the blur
6428                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6429                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture)
6430                                 {
6431                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6432                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6433                                         switch(vid.renderpath)
6434                                         {
6435                                         case RENDERPATH_GL11:
6436                                         case RENDERPATH_GL13:
6437                                         case RENDERPATH_GL20:
6438                                         case RENDERPATH_GLES1:
6439                                         case RENDERPATH_GLES2:
6440                                         case RENDERPATH_SOFT:
6441                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6442                                                 break;
6443                                         case RENDERPATH_D3D9:
6444                                         case RENDERPATH_D3D10:
6445                                         case RENDERPATH_D3D11:
6446                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6447                                                 break;
6448                                         }
6449                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true);
6450                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6451                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6452                                 }
6453
6454                                 // updates old view angles for next pass
6455                                 VectorCopy(cl.viewangles, blur_oldangles);
6456
6457                                 // copy view into the ghost texture
6458                                 if (!r_fb.ghosttexture)
6459                                         r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "motionblurtexture", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
6460                                 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);
6461                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6462                         }
6463                 }
6464                 else
6465                 {
6466                         // no r_fb.colortexture means we're rendering to the real fb
6467                         // we may still have to do view tint...
6468                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6469                         {
6470                                 // apply a color tint to the whole view
6471                                 R_ResetViewRendering2D(0, NULL, NULL);
6472                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6473                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6474                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6475                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6476                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6477                         }
6478                         break; // no screen processing, no bloom, skip it
6479                 }
6480
6481                 if (r_fb.bloomtexture[0])
6482                 {
6483                         // make the bloom texture
6484                         R_Bloom_MakeTexture();
6485                 }
6486
6487 #if _MSC_VER >= 1400
6488 #define sscanf sscanf_s
6489 #endif
6490                 memset(uservecs, 0, sizeof(uservecs));
6491                 if (r_glsl_postprocess_uservec1_enable.integer)
6492                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6493                 if (r_glsl_postprocess_uservec2_enable.integer)
6494                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6495                 if (r_glsl_postprocess_uservec3_enable.integer)
6496                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6497                 if (r_glsl_postprocess_uservec4_enable.integer)
6498                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6499
6500                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6501                 GL_Color(1, 1, 1, 1);
6502                 GL_BlendFunc(GL_ONE, GL_ZERO);
6503
6504                 switch(vid.renderpath)
6505                 {
6506                 case RENDERPATH_GL20:
6507                 case RENDERPATH_GLES2:
6508                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6509                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6510                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6511                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6512                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6513                         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]);
6514                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6515                         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]);
6516                         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]);
6517                         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]);
6518                         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]);
6519                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6520                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6521                         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);
6522                         break;
6523                 case RENDERPATH_D3D9:
6524 #ifdef SUPPORTD3D
6525                         // 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...
6526                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6527                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6528                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6529                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture);
6530                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6531                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6532                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6533                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6534                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6535                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6536                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6537                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6538                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6539                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6540 #endif
6541                         break;
6542                 case RENDERPATH_D3D10:
6543                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6544                         break;
6545                 case RENDERPATH_D3D11:
6546                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6547                         break;
6548                 case RENDERPATH_SOFT:
6549                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6550                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6551                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6552                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6553                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6554                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6555                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6556                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6557                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6558                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6559                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6560                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6561                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6562                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6563                         break;
6564                 default:
6565                         break;
6566                 }
6567                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6568                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6569                 break;
6570         case RENDERPATH_GL11:
6571         case RENDERPATH_GL13:
6572         case RENDERPATH_GLES1:
6573                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6574                 {
6575                         // apply a color tint to the whole view
6576                         R_ResetViewRendering2D(0, NULL, NULL);
6577                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6578                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6579                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6580                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6581                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6582                 }
6583                 break;
6584         }
6585 }
6586
6587 matrix4x4_t r_waterscrollmatrix;
6588
6589 void R_UpdateFog(void)
6590 {
6591         // Nehahra fog
6592         if (gamemode == GAME_NEHAHRA)
6593         {
6594                 if (gl_fogenable.integer)
6595                 {
6596                         r_refdef.oldgl_fogenable = true;
6597                         r_refdef.fog_density = gl_fogdensity.value;
6598                         r_refdef.fog_red = gl_fogred.value;
6599                         r_refdef.fog_green = gl_foggreen.value;
6600                         r_refdef.fog_blue = gl_fogblue.value;
6601                         r_refdef.fog_alpha = 1;
6602                         r_refdef.fog_start = 0;
6603                         r_refdef.fog_end = gl_skyclip.value;
6604                         r_refdef.fog_height = 1<<30;
6605                         r_refdef.fog_fadedepth = 128;
6606                 }
6607                 else if (r_refdef.oldgl_fogenable)
6608                 {
6609                         r_refdef.oldgl_fogenable = false;
6610                         r_refdef.fog_density = 0;
6611                         r_refdef.fog_red = 0;
6612                         r_refdef.fog_green = 0;
6613                         r_refdef.fog_blue = 0;
6614                         r_refdef.fog_alpha = 0;
6615                         r_refdef.fog_start = 0;
6616                         r_refdef.fog_end = 0;
6617                         r_refdef.fog_height = 1<<30;
6618                         r_refdef.fog_fadedepth = 128;
6619                 }
6620         }
6621
6622         // fog parms
6623         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6624         r_refdef.fog_start = max(0, r_refdef.fog_start);
6625         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6626
6627         if (r_refdef.fog_density && r_drawfog.integer)
6628         {
6629                 r_refdef.fogenabled = true;
6630                 // this is the point where the fog reaches 0.9986 alpha, which we
6631                 // consider a good enough cutoff point for the texture
6632                 // (0.9986 * 256 == 255.6)
6633                 if (r_fog_exp2.integer)
6634                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6635                 else
6636                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6637                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6638                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6639                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6640                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6641                         R_BuildFogHeightTexture();
6642                 // fog color was already set
6643                 // update the fog texture
6644                 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)
6645                         R_BuildFogTexture();
6646                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6647                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6648         }
6649         else
6650                 r_refdef.fogenabled = false;
6651
6652         // fog color
6653         if (r_refdef.fog_density)
6654         {
6655                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6656                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6657                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6658
6659                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6660                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6661                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6662                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6663
6664                 {
6665                         vec3_t fogvec;
6666                         VectorCopy(r_refdef.fogcolor, fogvec);
6667                         //   color.rgb *= ContrastBoost * SceneBrightness;
6668                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6669                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6670                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6671                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6672                 }
6673         }
6674 }
6675
6676 void R_UpdateVariables(void)
6677 {
6678         R_Textures_Frame();
6679
6680         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6681
6682         r_refdef.farclip = r_farclip_base.value;
6683         if (r_refdef.scene.worldmodel)
6684                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6685         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6686
6687         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6688                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6689         r_refdef.polygonfactor = 0;
6690         r_refdef.polygonoffset = 0;
6691         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6692         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6693
6694         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6695         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6696         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6697         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6698         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6699         if (FAKELIGHT_ENABLED)
6700         {
6701                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6702         }
6703         if (r_showsurfaces.integer)
6704         {
6705                 r_refdef.scene.rtworld = false;
6706                 r_refdef.scene.rtworldshadows = false;
6707                 r_refdef.scene.rtdlight = false;
6708                 r_refdef.scene.rtdlightshadows = false;
6709                 r_refdef.lightmapintensity = 0;
6710         }
6711
6712         switch(vid.renderpath)
6713         {
6714         case RENDERPATH_GL20:
6715         case RENDERPATH_D3D9:
6716         case RENDERPATH_D3D10:
6717         case RENDERPATH_D3D11:
6718         case RENDERPATH_SOFT:
6719         case RENDERPATH_GLES2:
6720                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6721                 {
6722                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6723                         {
6724                                 // build GLSL gamma texture
6725 #define RAMPWIDTH 256
6726                                 unsigned short ramp[RAMPWIDTH * 3];
6727                                 unsigned char rampbgr[RAMPWIDTH][4];
6728                                 int i;
6729
6730                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6731
6732                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6733                                 for(i = 0; i < RAMPWIDTH; ++i)
6734                                 {
6735                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6736                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6737                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6738                                         rampbgr[i][3] = 0;
6739                                 }
6740                                 if (r_texture_gammaramps)
6741                                 {
6742                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6743                                 }
6744                                 else
6745                                 {
6746                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6747                                 }
6748                         }
6749                 }
6750                 else
6751                 {
6752                         // remove GLSL gamma texture
6753                 }
6754                 break;
6755         case RENDERPATH_GL11:
6756         case RENDERPATH_GL13:
6757         case RENDERPATH_GLES1:
6758                 break;
6759         }
6760 }
6761
6762 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6763 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6764 /*
6765 ================
6766 R_SelectScene
6767 ================
6768 */
6769 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6770         if( scenetype != r_currentscenetype ) {
6771                 // store the old scenetype
6772                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6773                 r_currentscenetype = scenetype;
6774                 // move in the new scene
6775                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6776         }
6777 }
6778
6779 /*
6780 ================
6781 R_GetScenePointer
6782 ================
6783 */
6784 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6785 {
6786         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6787         if( scenetype == r_currentscenetype ) {
6788                 return &r_refdef.scene;
6789         } else {
6790                 return &r_scenes_store[ scenetype ];
6791         }
6792 }
6793
6794 int R_SortEntities_Compare(const void *ap, const void *bp)
6795 {
6796         const entity_render_t *a = *(const entity_render_t **)ap;
6797         const entity_render_t *b = *(const entity_render_t **)bp;
6798
6799         // 1. compare model
6800         if(a->model < b->model)
6801                 return -1;
6802         if(a->model > b->model)
6803                 return +1;
6804
6805         // 2. compare skin
6806         // TODO possibly calculate the REAL skinnum here first using
6807         // skinscenes?
6808         if(a->skinnum < b->skinnum)
6809                 return -1;
6810         if(a->skinnum > b->skinnum)
6811                 return +1;
6812
6813         // everything we compared is equal
6814         return 0;
6815 }
6816 void R_SortEntities(void)
6817 {
6818         // below or equal 2 ents, sorting never gains anything
6819         if(r_refdef.scene.numentities <= 2)
6820                 return;
6821         // sort
6822         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6823 }
6824
6825 /*
6826 ================
6827 R_RenderView
6828 ================
6829 */
6830 int dpsoftrast_test;
6831 extern void R_Shadow_UpdateBounceGridTexture(void);
6832 extern cvar_t r_shadow_bouncegrid;
6833 void R_RenderView(void)
6834 {
6835         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6836         int fbo;
6837         rtexture_t *depthtexture;
6838         rtexture_t *colortexture;
6839
6840         dpsoftrast_test = r_test.integer;
6841
6842         if (r_timereport_active)
6843                 R_TimeReport("start");
6844         r_textureframe++; // used only by R_GetCurrentTexture
6845         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6846
6847         if(R_CompileShader_CheckStaticParms())
6848                 R_GLSL_Restart_f();
6849
6850         if (!r_drawentities.integer)
6851                 r_refdef.scene.numentities = 0;
6852         else if (r_sortentities.integer)
6853                 R_SortEntities();
6854
6855         R_AnimCache_ClearCache();
6856         R_FrameData_NewFrame();
6857
6858         /* adjust for stereo display */
6859         if(R_Stereo_Active())
6860         {
6861                 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);
6862                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6863         }
6864
6865         if (r_refdef.view.isoverlay)
6866         {
6867                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6868                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6869                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6870                 R_TimeReport("depthclear");
6871
6872                 r_refdef.view.showdebug = false;
6873
6874                 r_fb.water.enabled = false;
6875                 r_fb.water.numwaterplanes = 0;
6876
6877                 R_RenderScene(0, NULL, NULL);
6878
6879                 r_refdef.view.matrix = originalmatrix;
6880
6881                 CHECKGLERROR
6882                 return;
6883         }
6884
6885         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6886         {
6887                 r_refdef.view.matrix = originalmatrix;
6888                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6889         }
6890
6891         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6892
6893         R_RenderView_UpdateViewVectors();
6894
6895         R_Shadow_UpdateWorldLightSelection();
6896
6897         R_Bloom_StartFrame();
6898         R_Water_StartFrame();
6899
6900         // now we probably have an fbo to render into
6901         fbo = r_fb.fbo;
6902         depthtexture = r_fb.depthtexture;
6903         colortexture = r_fb.colortexture;
6904
6905         CHECKGLERROR
6906         if (r_timereport_active)
6907                 R_TimeReport("viewsetup");
6908
6909         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6910
6911         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6912         {
6913                 R_ClearScreen(r_refdef.fogenabled);
6914                 if (r_timereport_active)
6915                         R_TimeReport("viewclear");
6916         }
6917         r_refdef.view.clear = true;
6918
6919         r_refdef.view.showdebug = true;
6920
6921         R_View_Update();
6922         if (r_timereport_active)
6923                 R_TimeReport("visibility");
6924
6925         R_Shadow_UpdateBounceGridTexture();
6926         if (r_timereport_active && r_shadow_bouncegrid.integer)
6927                 R_TimeReport("bouncegrid");
6928
6929         r_fb.water.numwaterplanes = 0;
6930         if (r_fb.water.enabled)
6931                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6932
6933         R_RenderScene(fbo, depthtexture, colortexture);
6934         r_fb.water.numwaterplanes = 0;
6935
6936         R_BlendView(fbo, depthtexture, colortexture);
6937         if (r_timereport_active)
6938                 R_TimeReport("blendview");
6939
6940         GL_Scissor(0, 0, vid.width, vid.height);
6941         GL_ScissorTest(false);
6942
6943         r_refdef.view.matrix = originalmatrix;
6944
6945         CHECKGLERROR
6946 }
6947
6948 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6949 {
6950         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6951         {
6952                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6953                 if (r_timereport_active)
6954                         R_TimeReport("waterworld");
6955         }
6956
6957         // don't let sound skip if going slow
6958         if (r_refdef.scene.extraupdate)
6959                 S_ExtraUpdate ();
6960
6961         R_DrawModelsAddWaterPlanes();
6962         if (r_timereport_active)
6963                 R_TimeReport("watermodels");
6964
6965         if (r_fb.water.numwaterplanes)
6966         {
6967                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6968                 if (r_timereport_active)
6969                         R_TimeReport("waterscenes");
6970         }
6971 }
6972
6973 extern void R_DrawLightningBeams (void);
6974 extern void VM_CL_AddPolygonsToMeshQueue (void);
6975 extern void R_DrawPortals (void);
6976 extern cvar_t cl_locs_show;
6977 static void R_DrawLocs(void);
6978 static void R_DrawEntityBBoxes(void);
6979 static void R_DrawModelDecals(void);
6980 extern void R_DrawModelShadows(void);
6981 extern void R_DrawModelShadowMaps(void);
6982 extern cvar_t cl_decals_newsystem;
6983 extern qboolean r_shadow_usingdeferredprepass;
6984 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6985 {
6986         qboolean shadowmapping = false;
6987
6988         if (r_timereport_active)
6989                 R_TimeReport("beginscene");
6990
6991         r_refdef.stats.renders++;
6992
6993         R_UpdateFog();
6994
6995         // don't let sound skip if going slow
6996         if (r_refdef.scene.extraupdate)
6997                 S_ExtraUpdate ();
6998
6999         R_MeshQueue_BeginScene();
7000
7001         R_SkyStartFrame();
7002
7003         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);
7004
7005         if (r_timereport_active)
7006                 R_TimeReport("skystartframe");
7007
7008         if (cl.csqc_vidvars.drawworld)
7009         {
7010                 // don't let sound skip if going slow
7011                 if (r_refdef.scene.extraupdate)
7012                         S_ExtraUpdate ();
7013
7014                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7015                 {
7016                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7017                         if (r_timereport_active)
7018                                 R_TimeReport("worldsky");
7019                 }
7020
7021                 if (R_DrawBrushModelsSky() && r_timereport_active)
7022                         R_TimeReport("bmodelsky");
7023
7024                 if (skyrendermasked && skyrenderlater)
7025                 {
7026                         // we have to force off the water clipping plane while rendering sky
7027                         R_SetupView(false, fbo, depthtexture, colortexture);
7028                         R_Sky();
7029                         R_SetupView(true, fbo, depthtexture, colortexture);
7030                         if (r_timereport_active)
7031                                 R_TimeReport("sky");
7032                 }
7033         }
7034
7035         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7036         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7037                 R_Shadow_PrepareModelShadows();
7038         if (r_timereport_active)
7039                 R_TimeReport("preparelights");
7040
7041         if (R_Shadow_ShadowMappingEnabled())
7042                 shadowmapping = true;
7043
7044         if (r_shadow_usingdeferredprepass)
7045                 R_Shadow_DrawPrepass();
7046
7047         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7048         {
7049                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7050                 if (r_timereport_active)
7051                         R_TimeReport("worlddepth");
7052         }
7053         if (r_depthfirst.integer >= 2)
7054         {
7055                 R_DrawModelsDepth();
7056                 if (r_timereport_active)
7057                         R_TimeReport("modeldepth");
7058         }
7059
7060         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7061         {
7062                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7063                 R_DrawModelShadowMaps();
7064                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7065                 // don't let sound skip if going slow
7066                 if (r_refdef.scene.extraupdate)
7067                         S_ExtraUpdate ();
7068         }
7069
7070         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7071         {
7072                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7073                 if (r_timereport_active)
7074                         R_TimeReport("world");
7075         }
7076
7077         // don't let sound skip if going slow
7078         if (r_refdef.scene.extraupdate)
7079                 S_ExtraUpdate ();
7080
7081         R_DrawModels();
7082         if (r_timereport_active)
7083                 R_TimeReport("models");
7084
7085         // don't let sound skip if going slow
7086         if (r_refdef.scene.extraupdate)
7087                 S_ExtraUpdate ();
7088
7089         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7090         {
7091                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7092                 R_DrawModelShadows();
7093                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7094                 // don't let sound skip if going slow
7095                 if (r_refdef.scene.extraupdate)
7096                         S_ExtraUpdate ();
7097         }
7098
7099         if (!r_shadow_usingdeferredprepass)
7100         {
7101                 R_Shadow_DrawLights();
7102                 if (r_timereport_active)
7103                         R_TimeReport("rtlights");
7104         }
7105
7106         // don't let sound skip if going slow
7107         if (r_refdef.scene.extraupdate)
7108                 S_ExtraUpdate ();
7109
7110         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7111         {
7112                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7113                 R_DrawModelShadows();
7114                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7115                 // don't let sound skip if going slow
7116                 if (r_refdef.scene.extraupdate)
7117                         S_ExtraUpdate ();
7118         }
7119
7120         if (cl.csqc_vidvars.drawworld)
7121         {
7122                 if (cl_decals_newsystem.integer)
7123                 {
7124                         R_DrawModelDecals();
7125                         if (r_timereport_active)
7126                                 R_TimeReport("modeldecals");
7127                 }
7128                 else
7129                 {
7130                         R_DrawDecals();
7131                         if (r_timereport_active)
7132                                 R_TimeReport("decals");
7133                 }
7134
7135                 R_DrawParticles();
7136                 if (r_timereport_active)
7137                         R_TimeReport("particles");
7138
7139                 R_DrawExplosions();
7140                 if (r_timereport_active)
7141                         R_TimeReport("explosions");
7142
7143                 R_DrawLightningBeams();
7144                 if (r_timereport_active)
7145                         R_TimeReport("lightning");
7146         }
7147
7148         VM_CL_AddPolygonsToMeshQueue();
7149
7150         if (r_refdef.view.showdebug)
7151         {
7152                 if (cl_locs_show.integer)
7153                 {
7154                         R_DrawLocs();
7155                         if (r_timereport_active)
7156                                 R_TimeReport("showlocs");
7157                 }
7158
7159                 if (r_drawportals.integer)
7160                 {
7161                         R_DrawPortals();
7162                         if (r_timereport_active)
7163                                 R_TimeReport("portals");
7164                 }
7165
7166                 if (r_showbboxes.value > 0)
7167                 {
7168                         R_DrawEntityBBoxes();
7169                         if (r_timereport_active)
7170                                 R_TimeReport("bboxes");
7171                 }
7172         }
7173
7174         if (r_transparent.integer)
7175         {
7176                 R_MeshQueue_RenderTransparent();
7177                 if (r_timereport_active)
7178                         R_TimeReport("drawtrans");
7179         }
7180
7181         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))
7182         {
7183                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7184                 if (r_timereport_active)
7185                         R_TimeReport("worlddebug");
7186                 R_DrawModelsDebug();
7187                 if (r_timereport_active)
7188                         R_TimeReport("modeldebug");
7189         }
7190
7191         if (cl.csqc_vidvars.drawworld)
7192         {
7193                 R_Shadow_DrawCoronas();
7194                 if (r_timereport_active)
7195                         R_TimeReport("coronas");
7196         }
7197
7198 #if 0
7199         {
7200                 GL_DepthTest(false);
7201                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7202                 GL_Color(1, 1, 1, 1);
7203                 qglBegin(GL_POLYGON);
7204                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7205                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7206                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7207                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7208                 qglEnd();
7209                 qglBegin(GL_POLYGON);
7210                 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]);
7211                 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]);
7212                 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]);
7213                 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]);
7214                 qglEnd();
7215                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7216         }
7217 #endif
7218
7219         // don't let sound skip if going slow
7220         if (r_refdef.scene.extraupdate)
7221                 S_ExtraUpdate ();
7222 }
7223
7224 static const unsigned short bboxelements[36] =
7225 {
7226         5, 1, 3, 5, 3, 7,
7227         6, 2, 0, 6, 0, 4,
7228         7, 3, 2, 7, 2, 6,
7229         4, 0, 1, 4, 1, 5,
7230         4, 5, 7, 4, 7, 6,
7231         1, 0, 2, 1, 2, 3,
7232 };
7233
7234 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7235 {
7236         int i;
7237         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7238
7239         RSurf_ActiveWorldEntity();
7240
7241         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7242         GL_DepthMask(false);
7243         GL_DepthRange(0, 1);
7244         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7245 //      R_Mesh_ResetTextureState();
7246
7247         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7248         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7249         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7250         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7251         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7252         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7253         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7254         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7255         R_FillColors(color4f, 8, cr, cg, cb, ca);
7256         if (r_refdef.fogenabled)
7257         {
7258                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7259                 {
7260                         f1 = RSurf_FogVertex(v);
7261                         f2 = 1 - f1;
7262                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7263                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7264                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7265                 }
7266         }
7267         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7268         R_Mesh_ResetTextureState();
7269         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7270         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7271 }
7272
7273 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7274 {
7275         int i;
7276         float color[4];
7277         prvm_edict_t *edict;
7278         prvm_prog_t *prog_save = prog;
7279
7280         // this function draws bounding boxes of server entities
7281         if (!sv.active)
7282                 return;
7283
7284         GL_CullFace(GL_NONE);
7285         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7286
7287         prog = 0;
7288         SV_VM_Begin();
7289         for (i = 0;i < numsurfaces;i++)
7290         {
7291                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7292                 switch ((int)PRVM_serveredictfloat(edict, solid))
7293                 {
7294                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7295                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7296                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7297                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7298                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7299                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7300                 }
7301                 color[3] *= r_showbboxes.value;
7302                 color[3] = bound(0, color[3], 1);
7303                 GL_DepthTest(!r_showdisabledepthtest.integer);
7304                 GL_CullFace(r_refdef.view.cullface_front);
7305                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7306         }
7307         SV_VM_End();
7308         prog = prog_save;
7309 }
7310
7311 static void R_DrawEntityBBoxes(void)
7312 {
7313         int i;
7314         prvm_edict_t *edict;
7315         vec3_t center;
7316         prvm_prog_t *prog_save = prog;
7317
7318         // this function draws bounding boxes of server entities
7319         if (!sv.active)
7320                 return;
7321
7322         prog = 0;
7323         SV_VM_Begin();
7324         for (i = 0;i < prog->num_edicts;i++)
7325         {
7326                 edict = PRVM_EDICT_NUM(i);
7327                 if (edict->priv.server->free)
7328                         continue;
7329                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7330                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7331                         continue;
7332                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7333                         continue;
7334                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7335                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7336         }
7337         SV_VM_End();
7338         prog = prog_save;
7339 }
7340
7341 static const int nomodelelement3i[24] =
7342 {
7343         5, 2, 0,
7344         5, 1, 2,
7345         5, 0, 3,
7346         5, 3, 1,
7347         0, 2, 4,
7348         2, 1, 4,
7349         3, 0, 4,
7350         1, 3, 4
7351 };
7352
7353 static const unsigned short nomodelelement3s[24] =
7354 {
7355         5, 2, 0,
7356         5, 1, 2,
7357         5, 0, 3,
7358         5, 3, 1,
7359         0, 2, 4,
7360         2, 1, 4,
7361         3, 0, 4,
7362         1, 3, 4
7363 };
7364
7365 static const float nomodelvertex3f[6*3] =
7366 {
7367         -16,   0,   0,
7368          16,   0,   0,
7369           0, -16,   0,
7370           0,  16,   0,
7371           0,   0, -16,
7372           0,   0,  16
7373 };
7374
7375 static const float nomodelcolor4f[6*4] =
7376 {
7377         0.0f, 0.0f, 0.5f, 1.0f,
7378         0.0f, 0.0f, 0.5f, 1.0f,
7379         0.0f, 0.5f, 0.0f, 1.0f,
7380         0.0f, 0.5f, 0.0f, 1.0f,
7381         0.5f, 0.0f, 0.0f, 1.0f,
7382         0.5f, 0.0f, 0.0f, 1.0f
7383 };
7384
7385 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7386 {
7387         int i;
7388         float f1, f2, *c;
7389         float color4f[6*4];
7390
7391         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);
7392
7393         // this is only called once per entity so numsurfaces is always 1, and
7394         // surfacelist is always {0}, so this code does not handle batches
7395
7396         if (rsurface.ent_flags & RENDER_ADDITIVE)
7397         {
7398                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7399                 GL_DepthMask(false);
7400         }
7401         else if (rsurface.colormod[3] < 1)
7402         {
7403                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7404                 GL_DepthMask(false);
7405         }
7406         else
7407         {
7408                 GL_BlendFunc(GL_ONE, GL_ZERO);
7409                 GL_DepthMask(true);
7410         }
7411         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7412         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7413         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7414         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7415         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7416         for (i = 0, c = color4f;i < 6;i++, c += 4)
7417         {
7418                 c[0] *= rsurface.colormod[0];
7419                 c[1] *= rsurface.colormod[1];
7420                 c[2] *= rsurface.colormod[2];
7421                 c[3] *= rsurface.colormod[3];
7422         }
7423         if (r_refdef.fogenabled)
7424         {
7425                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7426                 {
7427                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7428                         f2 = 1 - f1;
7429                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7430                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7431                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7432                 }
7433         }
7434 //      R_Mesh_ResetTextureState();
7435         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7436         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7437         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7438 }
7439
7440 void R_DrawNoModel(entity_render_t *ent)
7441 {
7442         vec3_t org;
7443         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7444         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7445                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7446         else
7447                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7448 }
7449
7450 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7451 {
7452         vec3_t right1, right2, diff, normal;
7453
7454         VectorSubtract (org2, org1, normal);
7455
7456         // calculate 'right' vector for start
7457         VectorSubtract (r_refdef.view.origin, org1, diff);
7458         CrossProduct (normal, diff, right1);
7459         VectorNormalize (right1);
7460
7461         // calculate 'right' vector for end
7462         VectorSubtract (r_refdef.view.origin, org2, diff);
7463         CrossProduct (normal, diff, right2);
7464         VectorNormalize (right2);
7465
7466         vert[ 0] = org1[0] + width * right1[0];
7467         vert[ 1] = org1[1] + width * right1[1];
7468         vert[ 2] = org1[2] + width * right1[2];
7469         vert[ 3] = org1[0] - width * right1[0];
7470         vert[ 4] = org1[1] - width * right1[1];
7471         vert[ 5] = org1[2] - width * right1[2];
7472         vert[ 6] = org2[0] - width * right2[0];
7473         vert[ 7] = org2[1] - width * right2[1];
7474         vert[ 8] = org2[2] - width * right2[2];
7475         vert[ 9] = org2[0] + width * right2[0];
7476         vert[10] = org2[1] + width * right2[1];
7477         vert[11] = org2[2] + width * right2[2];
7478 }
7479
7480 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)
7481 {
7482         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7483         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7484         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7485         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7486         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7487         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7488         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7489         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7490         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7491         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7492         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7493         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7494 }
7495
7496 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7497 {
7498         int i;
7499         float *vertex3f;
7500         float v[3];
7501         VectorSet(v, x, y, z);
7502         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7503                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7504                         break;
7505         if (i == mesh->numvertices)
7506         {
7507                 if (mesh->numvertices < mesh->maxvertices)
7508                 {
7509                         VectorCopy(v, vertex3f);
7510                         mesh->numvertices++;
7511                 }
7512                 return mesh->numvertices;
7513         }
7514         else
7515                 return i;
7516 }
7517
7518 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7519 {
7520         int i;
7521         int *e, element[3];
7522         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7523         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7524         e = mesh->element3i + mesh->numtriangles * 3;
7525         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7526         {
7527                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7528                 if (mesh->numtriangles < mesh->maxtriangles)
7529                 {
7530                         *e++ = element[0];
7531                         *e++ = element[1];
7532                         *e++ = element[2];
7533                         mesh->numtriangles++;
7534                 }
7535                 element[1] = element[2];
7536         }
7537 }
7538
7539 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7540 {
7541         int i;
7542         int *e, element[3];
7543         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7544         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7545         e = mesh->element3i + mesh->numtriangles * 3;
7546         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7547         {
7548                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7549                 if (mesh->numtriangles < mesh->maxtriangles)
7550                 {
7551                         *e++ = element[0];
7552                         *e++ = element[1];
7553                         *e++ = element[2];
7554                         mesh->numtriangles++;
7555                 }
7556                 element[1] = element[2];
7557         }
7558 }
7559
7560 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7561 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7562 {
7563         int planenum, planenum2;
7564         int w;
7565         int tempnumpoints;
7566         mplane_t *plane, *plane2;
7567         double maxdist;
7568         double temppoints[2][256*3];
7569         // figure out how large a bounding box we need to properly compute this brush
7570         maxdist = 0;
7571         for (w = 0;w < numplanes;w++)
7572                 maxdist = max(maxdist, fabs(planes[w].dist));
7573         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7574         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7575         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7576         {
7577                 w = 0;
7578                 tempnumpoints = 4;
7579                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7580                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7581                 {
7582                         if (planenum2 == planenum)
7583                                 continue;
7584                         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);
7585                         w = !w;
7586                 }
7587                 if (tempnumpoints < 3)
7588                         continue;
7589                 // generate elements forming a triangle fan for this polygon
7590                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7591         }
7592 }
7593
7594 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)
7595 {
7596         texturelayer_t *layer;
7597         layer = t->currentlayers + t->currentnumlayers++;
7598         layer->type = type;
7599         layer->depthmask = depthmask;
7600         layer->blendfunc1 = blendfunc1;
7601         layer->blendfunc2 = blendfunc2;
7602         layer->texture = texture;
7603         layer->texmatrix = *matrix;
7604         layer->color[0] = r;
7605         layer->color[1] = g;
7606         layer->color[2] = b;
7607         layer->color[3] = a;
7608 }
7609
7610 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7611 {
7612         if(parms[0] == 0 && parms[1] == 0)
7613                 return false;
7614         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7615                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7616                         return false;
7617         return true;
7618 }
7619
7620 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7621 {
7622         double index, f;
7623         index = parms[2] + rsurface.shadertime * parms[3];
7624         index -= floor(index);
7625         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7626         {
7627         default:
7628         case Q3WAVEFUNC_NONE:
7629         case Q3WAVEFUNC_NOISE:
7630         case Q3WAVEFUNC_COUNT:
7631                 f = 0;
7632                 break;
7633         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7634         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7635         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7636         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7637         case Q3WAVEFUNC_TRIANGLE:
7638                 index *= 4;
7639                 f = index - floor(index);
7640                 if (index < 1)
7641                 {
7642                         // f = f;
7643                 }
7644                 else if (index < 2)
7645                         f = 1 - f;
7646                 else if (index < 3)
7647                         f = -f;
7648                 else
7649                         f = -(1 - f);
7650                 break;
7651         }
7652         f = parms[0] + parms[1] * f;
7653         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7654                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7655         return (float) f;
7656 }
7657
7658 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7659 {
7660         int w, h, idx;
7661         double f;
7662         double offsetd[2];
7663         float tcmat[12];
7664         matrix4x4_t matrix, temp;
7665         switch(tcmod->tcmod)
7666         {
7667                 case Q3TCMOD_COUNT:
7668                 case Q3TCMOD_NONE:
7669                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7670                                 matrix = r_waterscrollmatrix;
7671                         else
7672                                 matrix = identitymatrix;
7673                         break;
7674                 case Q3TCMOD_ENTITYTRANSLATE:
7675                         // this is used in Q3 to allow the gamecode to control texcoord
7676                         // scrolling on the entity, which is not supported in darkplaces yet.
7677                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7678                         break;
7679                 case Q3TCMOD_ROTATE:
7680                         f = tcmod->parms[0] * rsurface.shadertime;
7681                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7682                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7683                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7684                         break;
7685                 case Q3TCMOD_SCALE:
7686                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7687                         break;
7688                 case Q3TCMOD_SCROLL:
7689                         // extra care is needed because of precision breakdown with large values of time
7690                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7691                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7692                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7693                         break;
7694                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7695                         w = (int) tcmod->parms[0];
7696                         h = (int) tcmod->parms[1];
7697                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7698                         f = f - floor(f);
7699                         idx = (int) floor(f * w * h);
7700                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7701                         break;
7702                 case Q3TCMOD_STRETCH:
7703                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7704                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7705                         break;
7706                 case Q3TCMOD_TRANSFORM:
7707                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7708                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7709                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7710                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7711                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7712                         break;
7713                 case Q3TCMOD_TURBULENT:
7714                         // this is handled in the RSurf_PrepareVertices function
7715                         matrix = identitymatrix;
7716                         break;
7717         }
7718         temp = *texmatrix;
7719         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7720 }
7721
7722 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7723 {
7724         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7725         char name[MAX_QPATH];
7726         skinframe_t *skinframe;
7727         unsigned char pixels[296*194];
7728         strlcpy(cache->name, skinname, sizeof(cache->name));
7729         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7730         if (developer_loading.integer)
7731                 Con_Printf("loading %s\n", name);
7732         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7733         if (!skinframe || !skinframe->base)
7734         {
7735                 unsigned char *f;
7736                 fs_offset_t filesize;
7737                 skinframe = NULL;
7738                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7739                 if (f)
7740                 {
7741                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7742                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7743                         Mem_Free(f);
7744                 }
7745         }
7746         cache->skinframe = skinframe;
7747 }
7748
7749 texture_t *R_GetCurrentTexture(texture_t *t)
7750 {
7751         int i;
7752         const entity_render_t *ent = rsurface.entity;
7753         dp_model_t *model = ent->model;
7754         q3shaderinfo_layer_tcmod_t *tcmod;
7755
7756         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7757                 return t->currentframe;
7758         t->update_lastrenderframe = r_textureframe;
7759         t->update_lastrenderentity = (void *)ent;
7760
7761         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7762                 t->camera_entity = ent->entitynumber;
7763         else
7764                 t->camera_entity = 0;
7765
7766         // switch to an alternate material if this is a q1bsp animated material
7767         {
7768                 texture_t *texture = t;
7769                 int s = rsurface.ent_skinnum;
7770                 if ((unsigned int)s >= (unsigned int)model->numskins)
7771                         s = 0;
7772                 if (model->skinscenes)
7773                 {
7774                         if (model->skinscenes[s].framecount > 1)
7775                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7776                         else
7777                                 s = model->skinscenes[s].firstframe;
7778                 }
7779                 if (s > 0)
7780                         t = t + s * model->num_surfaces;
7781                 if (t->animated)
7782                 {
7783                         // use an alternate animation if the entity's frame is not 0,
7784                         // and only if the texture has an alternate animation
7785                         if (rsurface.ent_alttextures && t->anim_total[1])
7786                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7787                         else
7788                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7789                 }
7790                 texture->currentframe = t;
7791         }
7792
7793         // update currentskinframe to be a qw skin or animation frame
7794         if (rsurface.ent_qwskin >= 0)
7795         {
7796                 i = rsurface.ent_qwskin;
7797                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7798                 {
7799                         r_qwskincache_size = cl.maxclients;
7800                         if (r_qwskincache)
7801                                 Mem_Free(r_qwskincache);
7802                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7803                 }
7804                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7805                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7806                 t->currentskinframe = r_qwskincache[i].skinframe;
7807                 if (t->currentskinframe == NULL)
7808                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7809         }
7810         else if (t->numskinframes >= 2)
7811                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7812         if (t->backgroundnumskinframes >= 2)
7813                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7814
7815         t->currentmaterialflags = t->basematerialflags;
7816         t->currentalpha = rsurface.colormod[3];
7817         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7818                 t->currentalpha *= r_wateralpha.value;
7819         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7820                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7821         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7822                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7823         if (!(rsurface.ent_flags & RENDER_LIGHT))
7824                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7825         else if (FAKELIGHT_ENABLED)
7826         {
7827                 // no modellight if using fakelight for the map
7828         }
7829         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7830         {
7831                 // pick a model lighting mode
7832                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7833                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7834                 else
7835                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7836         }
7837         if (rsurface.ent_flags & RENDER_ADDITIVE)
7838                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7839         else if (t->currentalpha < 1)
7840                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7841         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7842         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7843                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7844         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7845                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7846         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7847                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7848         if (t->backgroundnumskinframes)
7849                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7850         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7851         {
7852                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7853                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7854         }
7855         else
7856                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7857         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7858         {
7859                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7860                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7861         }
7862         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7863                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7864
7865         // there is no tcmod
7866         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7867         {
7868                 t->currenttexmatrix = r_waterscrollmatrix;
7869                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7870         }
7871         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7872         {
7873                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7874                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7875         }
7876
7877         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7878                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7879         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7880                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7881
7882         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7883         if (t->currentskinframe->qpixels)
7884                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7885         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7886         if (!t->basetexture)
7887                 t->basetexture = r_texture_notexture;
7888         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7889         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7890         t->nmaptexture = t->currentskinframe->nmap;
7891         if (!t->nmaptexture)
7892                 t->nmaptexture = r_texture_blanknormalmap;
7893         t->glosstexture = r_texture_black;
7894         t->glowtexture = t->currentskinframe->glow;
7895         t->fogtexture = t->currentskinframe->fog;
7896         t->reflectmasktexture = t->currentskinframe->reflect;
7897         if (t->backgroundnumskinframes)
7898         {
7899                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7900                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7901                 t->backgroundglosstexture = r_texture_black;
7902                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7903                 if (!t->backgroundnmaptexture)
7904                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7905         }
7906         else
7907         {
7908                 t->backgroundbasetexture = r_texture_white;
7909                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7910                 t->backgroundglosstexture = r_texture_black;
7911                 t->backgroundglowtexture = NULL;
7912         }
7913         t->specularpower = r_shadow_glossexponent.value;
7914         // TODO: store reference values for these in the texture?
7915         t->specularscale = 0;
7916         if (r_shadow_gloss.integer > 0)
7917         {
7918                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7919                 {
7920                         if (r_shadow_glossintensity.value > 0)
7921                         {
7922                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7923                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7924                                 t->specularscale = r_shadow_glossintensity.value;
7925                         }
7926                 }
7927                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7928                 {
7929                         t->glosstexture = r_texture_white;
7930                         t->backgroundglosstexture = r_texture_white;
7931                         t->specularscale = r_shadow_gloss2intensity.value;
7932                         t->specularpower = r_shadow_gloss2exponent.value;
7933                 }
7934         }
7935         t->specularscale *= t->specularscalemod;
7936         t->specularpower *= t->specularpowermod;
7937         t->rtlightambient = 0;
7938
7939         // lightmaps mode looks bad with dlights using actual texturing, so turn
7940         // off the colormap and glossmap, but leave the normalmap on as it still
7941         // accurately represents the shading involved
7942         if (gl_lightmaps.integer)
7943         {
7944                 t->basetexture = r_texture_grey128;
7945                 t->pantstexture = r_texture_black;
7946                 t->shirttexture = r_texture_black;
7947                 t->nmaptexture = r_texture_blanknormalmap;
7948                 t->glosstexture = r_texture_black;
7949                 t->glowtexture = NULL;
7950                 t->fogtexture = NULL;
7951                 t->reflectmasktexture = NULL;
7952                 t->backgroundbasetexture = NULL;
7953                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7954                 t->backgroundglosstexture = r_texture_black;
7955                 t->backgroundglowtexture = NULL;
7956                 t->specularscale = 0;
7957                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7958         }
7959
7960         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7961         VectorClear(t->dlightcolor);
7962         t->currentnumlayers = 0;
7963         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7964         {
7965                 int blendfunc1, blendfunc2;
7966                 qboolean depthmask;
7967                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7968                 {
7969                         blendfunc1 = GL_SRC_ALPHA;
7970                         blendfunc2 = GL_ONE;
7971                 }
7972                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7973                 {
7974                         blendfunc1 = GL_SRC_ALPHA;
7975                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7976                 }
7977                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7978                 {
7979                         blendfunc1 = t->customblendfunc[0];
7980                         blendfunc2 = t->customblendfunc[1];
7981                 }
7982                 else
7983                 {
7984                         blendfunc1 = GL_ONE;
7985                         blendfunc2 = GL_ZERO;
7986                 }
7987                 // don't colormod evilblend textures
7988                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7989                         VectorSet(t->lightmapcolor, 1, 1, 1);
7990                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7991                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7992                 {
7993                         // fullbright is not affected by r_refdef.lightmapintensity
7994                         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]);
7995                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7996                                 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]);
7997                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7998                                 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]);
7999                 }
8000                 else
8001                 {
8002                         vec3_t ambientcolor;
8003                         float colorscale;
8004                         // set the color tint used for lights affecting this surface
8005                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8006                         colorscale = 2;
8007                         // q3bsp has no lightmap updates, so the lightstylevalue that
8008                         // would normally be baked into the lightmap must be
8009                         // applied to the color
8010                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8011                         if (model->type == mod_brushq3)
8012                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8013                         colorscale *= r_refdef.lightmapintensity;
8014                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8015                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8016                         // basic lit geometry
8017                         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]);
8018                         // add pants/shirt if needed
8019                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8020                                 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]);
8021                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8022                                 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]);
8023                         // now add ambient passes if needed
8024                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8025                         {
8026                                 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]);
8027                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8028                                         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]);
8029                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8030                                         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]);
8031                         }
8032                 }
8033                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8034                         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]);
8035                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8036                 {
8037                         // if this is opaque use alpha blend which will darken the earlier
8038                         // passes cheaply.
8039                         //
8040                         // if this is an alpha blended material, all the earlier passes
8041                         // were darkened by fog already, so we only need to add the fog
8042                         // color ontop through the fog mask texture
8043                         //
8044                         // if this is an additive blended material, all the earlier passes
8045                         // were darkened by fog already, and we should not add fog color
8046                         // (because the background was not darkened, there is no fog color
8047                         // that was lost behind it).
8048                         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]);
8049                 }
8050         }
8051
8052         return t->currentframe;
8053 }
8054
8055 rsurfacestate_t rsurface;
8056
8057 void RSurf_ActiveWorldEntity(void)
8058 {
8059         dp_model_t *model = r_refdef.scene.worldmodel;
8060         //if (rsurface.entity == r_refdef.scene.worldentity)
8061         //      return;
8062         rsurface.entity = r_refdef.scene.worldentity;
8063         rsurface.skeleton = NULL;
8064         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8065         rsurface.ent_skinnum = 0;
8066         rsurface.ent_qwskin = -1;
8067         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8068         rsurface.shadertime = r_refdef.scene.time;
8069         rsurface.matrix = identitymatrix;
8070         rsurface.inversematrix = identitymatrix;
8071         rsurface.matrixscale = 1;
8072         rsurface.inversematrixscale = 1;
8073         R_EntityMatrix(&identitymatrix);
8074         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8075         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8076         rsurface.fograngerecip = r_refdef.fograngerecip;
8077         rsurface.fogheightfade = r_refdef.fogheightfade;
8078         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8079         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8080         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8081         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8082         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8083         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8084         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8085         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8086         rsurface.colormod[3] = 1;
8087         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);
8088         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8089         rsurface.frameblend[0].lerp = 1;
8090         rsurface.ent_alttextures = false;
8091         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8092         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8093         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8094         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8095         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8096         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8097         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8098         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8099         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8100         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8101         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8102         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8103         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8104         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8105         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8106         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8107         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8108         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8109         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8110         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8111         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8112         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8113         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8114         rsurface.modelelement3i = model->surfmesh.data_element3i;
8115         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8116         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8117         rsurface.modelelement3s = model->surfmesh.data_element3s;
8118         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8119         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8120         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8121         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8122         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8123         rsurface.modelsurfaces = model->data_surfaces;
8124         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8125         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8126         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8127         rsurface.modelgeneratedvertex = false;
8128         rsurface.batchgeneratedvertex = false;
8129         rsurface.batchfirstvertex = 0;
8130         rsurface.batchnumvertices = 0;
8131         rsurface.batchfirsttriangle = 0;
8132         rsurface.batchnumtriangles = 0;
8133         rsurface.batchvertex3f  = NULL;
8134         rsurface.batchvertex3f_vertexbuffer = NULL;
8135         rsurface.batchvertex3f_bufferoffset = 0;
8136         rsurface.batchsvector3f = NULL;
8137         rsurface.batchsvector3f_vertexbuffer = NULL;
8138         rsurface.batchsvector3f_bufferoffset = 0;
8139         rsurface.batchtvector3f = NULL;
8140         rsurface.batchtvector3f_vertexbuffer = NULL;
8141         rsurface.batchtvector3f_bufferoffset = 0;
8142         rsurface.batchnormal3f  = NULL;
8143         rsurface.batchnormal3f_vertexbuffer = NULL;
8144         rsurface.batchnormal3f_bufferoffset = 0;
8145         rsurface.batchlightmapcolor4f = NULL;
8146         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8147         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8148         rsurface.batchtexcoordtexture2f = NULL;
8149         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8150         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8151         rsurface.batchtexcoordlightmap2f = NULL;
8152         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8153         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8154         rsurface.batchvertexmesh = NULL;
8155         rsurface.batchvertexmeshbuffer = NULL;
8156         rsurface.batchvertex3fbuffer = NULL;
8157         rsurface.batchelement3i = NULL;
8158         rsurface.batchelement3i_indexbuffer = NULL;
8159         rsurface.batchelement3i_bufferoffset = 0;
8160         rsurface.batchelement3s = NULL;
8161         rsurface.batchelement3s_indexbuffer = NULL;
8162         rsurface.batchelement3s_bufferoffset = 0;
8163         rsurface.passcolor4f = NULL;
8164         rsurface.passcolor4f_vertexbuffer = NULL;
8165         rsurface.passcolor4f_bufferoffset = 0;
8166 }
8167
8168 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8169 {
8170         dp_model_t *model = ent->model;
8171         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8172         //      return;
8173         rsurface.entity = (entity_render_t *)ent;
8174         rsurface.skeleton = ent->skeleton;
8175         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8176         rsurface.ent_skinnum = ent->skinnum;
8177         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;
8178         rsurface.ent_flags = ent->flags;
8179         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8180         rsurface.matrix = ent->matrix;
8181         rsurface.inversematrix = ent->inversematrix;
8182         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8183         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8184         R_EntityMatrix(&rsurface.matrix);
8185         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8186         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8187         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8188         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8189         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8190         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8191         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8192         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8193         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8194         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8195         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8196         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8197         rsurface.colormod[3] = ent->alpha;
8198         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8199         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8200         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8201         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8202         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8203         if (ent->model->brush.submodel && !prepass)
8204         {
8205                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8206                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8207         }
8208         if (model->surfmesh.isanimated && model->AnimateVertices)
8209         {
8210                 if (ent->animcache_vertex3f)
8211                 {
8212                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8213                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8214                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8215                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8216                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8217                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8218                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8219                 }
8220                 else if (wanttangents)
8221                 {
8222                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8223                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8224                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8225                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8226                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8227                         rsurface.modelvertexmesh = NULL;
8228                         rsurface.modelvertexmeshbuffer = NULL;
8229                         rsurface.modelvertex3fbuffer = NULL;
8230                 }
8231                 else if (wantnormals)
8232                 {
8233                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8234                         rsurface.modelsvector3f = NULL;
8235                         rsurface.modeltvector3f = NULL;
8236                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8237                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8238                         rsurface.modelvertexmesh = NULL;
8239                         rsurface.modelvertexmeshbuffer = NULL;
8240                         rsurface.modelvertex3fbuffer = NULL;
8241                 }
8242                 else
8243                 {
8244                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8245                         rsurface.modelsvector3f = NULL;
8246                         rsurface.modeltvector3f = NULL;
8247                         rsurface.modelnormal3f = NULL;
8248                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8249                         rsurface.modelvertexmesh = NULL;
8250                         rsurface.modelvertexmeshbuffer = NULL;
8251                         rsurface.modelvertex3fbuffer = NULL;
8252                 }
8253                 rsurface.modelvertex3f_vertexbuffer = 0;
8254                 rsurface.modelvertex3f_bufferoffset = 0;
8255                 rsurface.modelsvector3f_vertexbuffer = 0;
8256                 rsurface.modelsvector3f_bufferoffset = 0;
8257                 rsurface.modeltvector3f_vertexbuffer = 0;
8258                 rsurface.modeltvector3f_bufferoffset = 0;
8259                 rsurface.modelnormal3f_vertexbuffer = 0;
8260                 rsurface.modelnormal3f_bufferoffset = 0;
8261                 rsurface.modelgeneratedvertex = true;
8262         }
8263         else
8264         {
8265                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8266                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8267                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8268                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8269                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8270                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8271                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8272                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8273                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8274                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8275                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8276                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8277                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8278                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8279                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8280                 rsurface.modelgeneratedvertex = false;
8281         }
8282         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8283         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8284         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8285         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8286         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8287         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8288         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8289         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8290         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8291         rsurface.modelelement3i = model->surfmesh.data_element3i;
8292         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8293         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8294         rsurface.modelelement3s = model->surfmesh.data_element3s;
8295         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8296         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8297         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8298         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8299         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8300         rsurface.modelsurfaces = model->data_surfaces;
8301         rsurface.batchgeneratedvertex = false;
8302         rsurface.batchfirstvertex = 0;
8303         rsurface.batchnumvertices = 0;
8304         rsurface.batchfirsttriangle = 0;
8305         rsurface.batchnumtriangles = 0;
8306         rsurface.batchvertex3f  = NULL;
8307         rsurface.batchvertex3f_vertexbuffer = NULL;
8308         rsurface.batchvertex3f_bufferoffset = 0;
8309         rsurface.batchsvector3f = NULL;
8310         rsurface.batchsvector3f_vertexbuffer = NULL;
8311         rsurface.batchsvector3f_bufferoffset = 0;
8312         rsurface.batchtvector3f = NULL;
8313         rsurface.batchtvector3f_vertexbuffer = NULL;
8314         rsurface.batchtvector3f_bufferoffset = 0;
8315         rsurface.batchnormal3f  = NULL;
8316         rsurface.batchnormal3f_vertexbuffer = NULL;
8317         rsurface.batchnormal3f_bufferoffset = 0;
8318         rsurface.batchlightmapcolor4f = NULL;
8319         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8320         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8321         rsurface.batchtexcoordtexture2f = NULL;
8322         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8323         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8324         rsurface.batchtexcoordlightmap2f = NULL;
8325         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8326         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8327         rsurface.batchvertexmesh = NULL;
8328         rsurface.batchvertexmeshbuffer = NULL;
8329         rsurface.batchvertex3fbuffer = NULL;
8330         rsurface.batchelement3i = NULL;
8331         rsurface.batchelement3i_indexbuffer = NULL;
8332         rsurface.batchelement3i_bufferoffset = 0;
8333         rsurface.batchelement3s = NULL;
8334         rsurface.batchelement3s_indexbuffer = NULL;
8335         rsurface.batchelement3s_bufferoffset = 0;
8336         rsurface.passcolor4f = NULL;
8337         rsurface.passcolor4f_vertexbuffer = NULL;
8338         rsurface.passcolor4f_bufferoffset = 0;
8339 }
8340
8341 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)
8342 {
8343         rsurface.entity = r_refdef.scene.worldentity;
8344         rsurface.skeleton = NULL;
8345         rsurface.ent_skinnum = 0;
8346         rsurface.ent_qwskin = -1;
8347         rsurface.ent_flags = entflags;
8348         rsurface.shadertime = r_refdef.scene.time - shadertime;
8349         rsurface.modelnumvertices = numvertices;
8350         rsurface.modelnumtriangles = numtriangles;
8351         rsurface.matrix = *matrix;
8352         rsurface.inversematrix = *inversematrix;
8353         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8354         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8355         R_EntityMatrix(&rsurface.matrix);
8356         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8357         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8358         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8359         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8360         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8361         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8362         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8363         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8364         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8365         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8366         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8367         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8368         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);
8369         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8370         rsurface.frameblend[0].lerp = 1;
8371         rsurface.ent_alttextures = false;
8372         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8373         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8374         if (wanttangents)
8375         {
8376                 rsurface.modelvertex3f = (float *)vertex3f;
8377                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8378                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8379                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8380         }
8381         else if (wantnormals)
8382         {
8383                 rsurface.modelvertex3f = (float *)vertex3f;
8384                 rsurface.modelsvector3f = NULL;
8385                 rsurface.modeltvector3f = NULL;
8386                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8387         }
8388         else
8389         {
8390                 rsurface.modelvertex3f = (float *)vertex3f;
8391                 rsurface.modelsvector3f = NULL;
8392                 rsurface.modeltvector3f = NULL;
8393                 rsurface.modelnormal3f = NULL;
8394         }
8395         rsurface.modelvertexmesh = NULL;
8396         rsurface.modelvertexmeshbuffer = NULL;
8397         rsurface.modelvertex3fbuffer = NULL;
8398         rsurface.modelvertex3f_vertexbuffer = 0;
8399         rsurface.modelvertex3f_bufferoffset = 0;
8400         rsurface.modelsvector3f_vertexbuffer = 0;
8401         rsurface.modelsvector3f_bufferoffset = 0;
8402         rsurface.modeltvector3f_vertexbuffer = 0;
8403         rsurface.modeltvector3f_bufferoffset = 0;
8404         rsurface.modelnormal3f_vertexbuffer = 0;
8405         rsurface.modelnormal3f_bufferoffset = 0;
8406         rsurface.modelgeneratedvertex = true;
8407         rsurface.modellightmapcolor4f  = (float *)color4f;
8408         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8409         rsurface.modellightmapcolor4f_bufferoffset = 0;
8410         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8411         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8412         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8413         rsurface.modeltexcoordlightmap2f  = NULL;
8414         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8415         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8416         rsurface.modelelement3i = (int *)element3i;
8417         rsurface.modelelement3i_indexbuffer = NULL;
8418         rsurface.modelelement3i_bufferoffset = 0;
8419         rsurface.modelelement3s = (unsigned short *)element3s;
8420         rsurface.modelelement3s_indexbuffer = NULL;
8421         rsurface.modelelement3s_bufferoffset = 0;
8422         rsurface.modellightmapoffsets = NULL;
8423         rsurface.modelsurfaces = NULL;
8424         rsurface.batchgeneratedvertex = false;
8425         rsurface.batchfirstvertex = 0;
8426         rsurface.batchnumvertices = 0;
8427         rsurface.batchfirsttriangle = 0;
8428         rsurface.batchnumtriangles = 0;
8429         rsurface.batchvertex3f  = NULL;
8430         rsurface.batchvertex3f_vertexbuffer = NULL;
8431         rsurface.batchvertex3f_bufferoffset = 0;
8432         rsurface.batchsvector3f = NULL;
8433         rsurface.batchsvector3f_vertexbuffer = NULL;
8434         rsurface.batchsvector3f_bufferoffset = 0;
8435         rsurface.batchtvector3f = NULL;
8436         rsurface.batchtvector3f_vertexbuffer = NULL;
8437         rsurface.batchtvector3f_bufferoffset = 0;
8438         rsurface.batchnormal3f  = NULL;
8439         rsurface.batchnormal3f_vertexbuffer = NULL;
8440         rsurface.batchnormal3f_bufferoffset = 0;
8441         rsurface.batchlightmapcolor4f = NULL;
8442         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8443         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8444         rsurface.batchtexcoordtexture2f = NULL;
8445         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8446         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8447         rsurface.batchtexcoordlightmap2f = NULL;
8448         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8449         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8450         rsurface.batchvertexmesh = NULL;
8451         rsurface.batchvertexmeshbuffer = NULL;
8452         rsurface.batchvertex3fbuffer = NULL;
8453         rsurface.batchelement3i = NULL;
8454         rsurface.batchelement3i_indexbuffer = NULL;
8455         rsurface.batchelement3i_bufferoffset = 0;
8456         rsurface.batchelement3s = NULL;
8457         rsurface.batchelement3s_indexbuffer = NULL;
8458         rsurface.batchelement3s_bufferoffset = 0;
8459         rsurface.passcolor4f = NULL;
8460         rsurface.passcolor4f_vertexbuffer = NULL;
8461         rsurface.passcolor4f_bufferoffset = 0;
8462
8463         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8464         {
8465                 if ((wantnormals || wanttangents) && !normal3f)
8466                 {
8467                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8468                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8469                 }
8470                 if (wanttangents && !svector3f)
8471                 {
8472                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8473                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8474                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8475                 }
8476         }
8477 }
8478
8479 float RSurf_FogPoint(const float *v)
8480 {
8481         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8482         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8483         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8484         float FogHeightFade = r_refdef.fogheightfade;
8485         float fogfrac;
8486         unsigned int fogmasktableindex;
8487         if (r_refdef.fogplaneviewabove)
8488                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8489         else
8490                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8491         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8492         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8493 }
8494
8495 float RSurf_FogVertex(const float *v)
8496 {
8497         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8498         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8499         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8500         float FogHeightFade = rsurface.fogheightfade;
8501         float fogfrac;
8502         unsigned int fogmasktableindex;
8503         if (r_refdef.fogplaneviewabove)
8504                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8505         else
8506                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8507         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8508         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8509 }
8510
8511 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8512 {
8513         int i;
8514         for (i = 0;i < numelements;i++)
8515                 outelement3i[i] = inelement3i[i] + adjust;
8516 }
8517
8518 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8519 extern cvar_t gl_vbo;
8520 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8521 {
8522         int deformindex;
8523         int firsttriangle;
8524         int numtriangles;
8525         int firstvertex;
8526         int endvertex;
8527         int numvertices;
8528         int surfacefirsttriangle;
8529         int surfacenumtriangles;
8530         int surfacefirstvertex;
8531         int surfaceendvertex;
8532         int surfacenumvertices;
8533         int batchnumvertices;
8534         int batchnumtriangles;
8535         int needsupdate;
8536         int i, j;
8537         qboolean gaps;
8538         qboolean dynamicvertex;
8539         float amplitude;
8540         float animpos;
8541         float scale;
8542         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8543         float waveparms[4];
8544         q3shaderinfo_deform_t *deform;
8545         const msurface_t *surface, *firstsurface;
8546         r_vertexmesh_t *vertexmesh;
8547         if (!texturenumsurfaces)
8548                 return;
8549         // find vertex range of this surface batch
8550         gaps = false;
8551         firstsurface = texturesurfacelist[0];
8552         firsttriangle = firstsurface->num_firsttriangle;
8553         batchnumvertices = 0;
8554         batchnumtriangles = 0;
8555         firstvertex = endvertex = firstsurface->num_firstvertex;
8556         for (i = 0;i < texturenumsurfaces;i++)
8557         {
8558                 surface = texturesurfacelist[i];
8559                 if (surface != firstsurface + i)
8560                         gaps = true;
8561                 surfacefirstvertex = surface->num_firstvertex;
8562                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8563                 surfacenumvertices = surface->num_vertices;
8564                 surfacenumtriangles = surface->num_triangles;
8565                 if (firstvertex > surfacefirstvertex)
8566                         firstvertex = surfacefirstvertex;
8567                 if (endvertex < surfaceendvertex)
8568                         endvertex = surfaceendvertex;
8569                 batchnumvertices += surfacenumvertices;
8570                 batchnumtriangles += surfacenumtriangles;
8571         }
8572
8573         // we now know the vertex range used, and if there are any gaps in it
8574         rsurface.batchfirstvertex = firstvertex;
8575         rsurface.batchnumvertices = endvertex - firstvertex;
8576         rsurface.batchfirsttriangle = firsttriangle;
8577         rsurface.batchnumtriangles = batchnumtriangles;
8578
8579         // this variable holds flags for which properties have been updated that
8580         // may require regenerating vertexmesh array...
8581         needsupdate = 0;
8582
8583         // check if any dynamic vertex processing must occur
8584         dynamicvertex = false;
8585
8586         // if there is a chance of animated vertex colors, it's a dynamic batch
8587         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8588         {
8589                 dynamicvertex = true;
8590                 batchneed |= BATCHNEED_NOGAPS;
8591                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8592         }
8593
8594         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8595         {
8596                 switch (deform->deform)
8597                 {
8598                 default:
8599                 case Q3DEFORM_PROJECTIONSHADOW:
8600                 case Q3DEFORM_TEXT0:
8601                 case Q3DEFORM_TEXT1:
8602                 case Q3DEFORM_TEXT2:
8603                 case Q3DEFORM_TEXT3:
8604                 case Q3DEFORM_TEXT4:
8605                 case Q3DEFORM_TEXT5:
8606                 case Q3DEFORM_TEXT6:
8607                 case Q3DEFORM_TEXT7:
8608                 case Q3DEFORM_NONE:
8609                         break;
8610                 case Q3DEFORM_AUTOSPRITE:
8611                         dynamicvertex = true;
8612                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8613                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8614                         break;
8615                 case Q3DEFORM_AUTOSPRITE2:
8616                         dynamicvertex = true;
8617                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8618                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8619                         break;
8620                 case Q3DEFORM_NORMAL:
8621                         dynamicvertex = true;
8622                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8623                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8624                         break;
8625                 case Q3DEFORM_WAVE:
8626                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8627                                 break; // if wavefunc is a nop, ignore this transform
8628                         dynamicvertex = true;
8629                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8630                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8631                         break;
8632                 case Q3DEFORM_BULGE:
8633                         dynamicvertex = true;
8634                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8635                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8636                         break;
8637                 case Q3DEFORM_MOVE:
8638                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8639                                 break; // if wavefunc is a nop, ignore this transform
8640                         dynamicvertex = true;
8641                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8642                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8643                         break;
8644                 }
8645         }
8646         switch(rsurface.texture->tcgen.tcgen)
8647         {
8648         default:
8649         case Q3TCGEN_TEXTURE:
8650                 break;
8651         case Q3TCGEN_LIGHTMAP:
8652                 dynamicvertex = true;
8653                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8654                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8655                 break;
8656         case Q3TCGEN_VECTOR:
8657                 dynamicvertex = true;
8658                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8659                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8660                 break;
8661         case Q3TCGEN_ENVIRONMENT:
8662                 dynamicvertex = true;
8663                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8664                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8665                 break;
8666         }
8667         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8668         {
8669                 dynamicvertex = true;
8670                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8671                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8672         }
8673
8674         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8675         {
8676                 dynamicvertex = true;
8677                 batchneed |= BATCHNEED_NOGAPS;
8678                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8679         }
8680
8681         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8682         {
8683                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8684                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8685                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8686                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8687                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8688                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8689                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8690         }
8691
8692         // when the model data has no vertex buffer (dynamic mesh), we need to
8693         // eliminate gaps
8694         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8695                 batchneed |= BATCHNEED_NOGAPS;
8696
8697         // if needsupdate, we have to do a dynamic vertex batch for sure
8698         if (needsupdate & batchneed)
8699                 dynamicvertex = true;
8700
8701         // see if we need to build vertexmesh from arrays
8702         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8703                 dynamicvertex = true;
8704
8705         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8706         // also some drivers strongly dislike firstvertex
8707         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8708                 dynamicvertex = true;
8709
8710         rsurface.batchvertex3f = rsurface.modelvertex3f;
8711         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8712         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8713         rsurface.batchsvector3f = rsurface.modelsvector3f;
8714         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8715         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8716         rsurface.batchtvector3f = rsurface.modeltvector3f;
8717         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8718         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8719         rsurface.batchnormal3f = rsurface.modelnormal3f;
8720         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8721         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8722         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8723         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8724         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8725         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8726         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8727         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8728         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8729         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8730         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8731         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8732         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8733         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8734         rsurface.batchelement3i = rsurface.modelelement3i;
8735         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8736         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8737         rsurface.batchelement3s = rsurface.modelelement3s;
8738         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8739         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8740
8741         // if any dynamic vertex processing has to occur in software, we copy the
8742         // entire surface list together before processing to rebase the vertices
8743         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8744         //
8745         // if any gaps exist and we do not have a static vertex buffer, we have to
8746         // copy the surface list together to avoid wasting upload bandwidth on the
8747         // vertices in the gaps.
8748         //
8749         // if gaps exist and we have a static vertex buffer, we still have to
8750         // combine the index buffer ranges into one dynamic index buffer.
8751         //
8752         // in all cases we end up with data that can be drawn in one call.
8753
8754         if (!dynamicvertex)
8755         {
8756                 // static vertex data, just set pointers...
8757                 rsurface.batchgeneratedvertex = false;
8758                 // if there are gaps, we want to build a combined index buffer,
8759                 // otherwise use the original static buffer with an appropriate offset
8760                 if (gaps)
8761                 {
8762                         // build a new triangle elements array for this batch
8763                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8764                         rsurface.batchfirsttriangle = 0;
8765                         numtriangles = 0;
8766                         for (i = 0;i < texturenumsurfaces;i++)
8767                         {
8768                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8769                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8770                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8771                                 numtriangles += surfacenumtriangles;
8772                         }
8773                         rsurface.batchelement3i_indexbuffer = NULL;
8774                         rsurface.batchelement3i_bufferoffset = 0;
8775                         rsurface.batchelement3s = NULL;
8776                         rsurface.batchelement3s_indexbuffer = NULL;
8777                         rsurface.batchelement3s_bufferoffset = 0;
8778                         if (endvertex <= 65536)
8779                         {
8780                                 // make a 16bit (unsigned short) index array if possible
8781                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8782                                 for (i = 0;i < numtriangles*3;i++)
8783                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8784                         }
8785                 }
8786                 return;
8787         }
8788
8789         // something needs software processing, do it for real...
8790         // we only directly handle separate array data in this case and then
8791         // generate interleaved data if needed...
8792         rsurface.batchgeneratedvertex = true;
8793
8794         // now copy the vertex data into a combined array and make an index array
8795         // (this is what Quake3 does all the time)
8796         //if (gaps || rsurface.batchfirstvertex)
8797         {
8798                 rsurface.batchvertex3fbuffer = NULL;
8799                 rsurface.batchvertexmesh = NULL;
8800                 rsurface.batchvertexmeshbuffer = NULL;
8801                 rsurface.batchvertex3f = NULL;
8802                 rsurface.batchvertex3f_vertexbuffer = NULL;
8803                 rsurface.batchvertex3f_bufferoffset = 0;
8804                 rsurface.batchsvector3f = NULL;
8805                 rsurface.batchsvector3f_vertexbuffer = NULL;
8806                 rsurface.batchsvector3f_bufferoffset = 0;
8807                 rsurface.batchtvector3f = NULL;
8808                 rsurface.batchtvector3f_vertexbuffer = NULL;
8809                 rsurface.batchtvector3f_bufferoffset = 0;
8810                 rsurface.batchnormal3f = NULL;
8811                 rsurface.batchnormal3f_vertexbuffer = NULL;
8812                 rsurface.batchnormal3f_bufferoffset = 0;
8813                 rsurface.batchlightmapcolor4f = NULL;
8814                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8815                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8816                 rsurface.batchtexcoordtexture2f = NULL;
8817                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8818                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8819                 rsurface.batchtexcoordlightmap2f = NULL;
8820                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8821                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8822                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8823                 rsurface.batchelement3i_indexbuffer = NULL;
8824                 rsurface.batchelement3i_bufferoffset = 0;
8825                 rsurface.batchelement3s = NULL;
8826                 rsurface.batchelement3s_indexbuffer = NULL;
8827                 rsurface.batchelement3s_bufferoffset = 0;
8828                 // we'll only be setting up certain arrays as needed
8829                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8830                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8831                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8832                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8833                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8834                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8835                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8836                 {
8837                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8838                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8839                 }
8840                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8841                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8842                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8843                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8844                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8845                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8846                 numvertices = 0;
8847                 numtriangles = 0;
8848                 for (i = 0;i < texturenumsurfaces;i++)
8849                 {
8850                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8851                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8852                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8853                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8854                         // copy only the data requested
8855                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8856                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8857                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8858                         {
8859                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8860                                 {
8861                                         if (rsurface.batchvertex3f)
8862                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8863                                         else
8864                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8865                                 }
8866                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8867                                 {
8868                                         if (rsurface.modelnormal3f)
8869                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8870                                         else
8871                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8872                                 }
8873                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8874                                 {
8875                                         if (rsurface.modelsvector3f)
8876                                         {
8877                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8878                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8879                                         }
8880                                         else
8881                                         {
8882                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8883                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8884                                         }
8885                                 }
8886                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8887                                 {
8888                                         if (rsurface.modellightmapcolor4f)
8889                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8890                                         else
8891                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8892                                 }
8893                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8894                                 {
8895                                         if (rsurface.modeltexcoordtexture2f)
8896                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8897                                         else
8898                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8899                                 }
8900                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8901                                 {
8902                                         if (rsurface.modeltexcoordlightmap2f)
8903                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8904                                         else
8905                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8906                                 }
8907                         }
8908                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8909                         numvertices += surfacenumvertices;
8910                         numtriangles += surfacenumtriangles;
8911                 }
8912
8913                 // generate a 16bit index array as well if possible
8914                 // (in general, dynamic batches fit)
8915                 if (numvertices <= 65536)
8916                 {
8917                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8918                         for (i = 0;i < numtriangles*3;i++)
8919                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8920                 }
8921
8922                 // since we've copied everything, the batch now starts at 0
8923                 rsurface.batchfirstvertex = 0;
8924                 rsurface.batchnumvertices = batchnumvertices;
8925                 rsurface.batchfirsttriangle = 0;
8926                 rsurface.batchnumtriangles = batchnumtriangles;
8927         }
8928
8929         // q1bsp surfaces rendered in vertex color mode have to have colors
8930         // calculated based on lightstyles
8931         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8932         {
8933                 // generate color arrays for the surfaces in this list
8934                 int c[4];
8935                 int scale;
8936                 int size3;
8937                 const int *offsets;
8938                 const unsigned char *lm;
8939                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8940                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8941                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8942                 numvertices = 0;
8943                 for (i = 0;i < texturenumsurfaces;i++)
8944                 {
8945                         surface = texturesurfacelist[i];
8946                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8947                         surfacenumvertices = surface->num_vertices;
8948                         if (surface->lightmapinfo->samples)
8949                         {
8950                                 for (j = 0;j < surfacenumvertices;j++)
8951                                 {
8952                                         lm = surface->lightmapinfo->samples + offsets[j];
8953                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8954                                         VectorScale(lm, scale, c);
8955                                         if (surface->lightmapinfo->styles[1] != 255)
8956                                         {
8957                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8958                                                 lm += size3;
8959                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8960                                                 VectorMA(c, scale, lm, c);
8961                                                 if (surface->lightmapinfo->styles[2] != 255)
8962                                                 {
8963                                                         lm += size3;
8964                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8965                                                         VectorMA(c, scale, lm, c);
8966                                                         if (surface->lightmapinfo->styles[3] != 255)
8967                                                         {
8968                                                                 lm += size3;
8969                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8970                                                                 VectorMA(c, scale, lm, c);
8971                                                         }
8972                                                 }
8973                                         }
8974                                         c[0] >>= 7;
8975                                         c[1] >>= 7;
8976                                         c[2] >>= 7;
8977                                         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);
8978                                         numvertices++;
8979                                 }
8980                         }
8981                         else
8982                         {
8983                                 for (j = 0;j < surfacenumvertices;j++)
8984                                 {
8985                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8986                                         numvertices++;
8987                                 }
8988                         }
8989                 }
8990         }
8991
8992         // if vertices are deformed (sprite flares and things in maps, possibly
8993         // water waves, bulges and other deformations), modify the copied vertices
8994         // in place
8995         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8996         {
8997                 switch (deform->deform)
8998                 {
8999                 default:
9000                 case Q3DEFORM_PROJECTIONSHADOW:
9001                 case Q3DEFORM_TEXT0:
9002                 case Q3DEFORM_TEXT1:
9003                 case Q3DEFORM_TEXT2:
9004                 case Q3DEFORM_TEXT3:
9005                 case Q3DEFORM_TEXT4:
9006                 case Q3DEFORM_TEXT5:
9007                 case Q3DEFORM_TEXT6:
9008                 case Q3DEFORM_TEXT7:
9009                 case Q3DEFORM_NONE:
9010                         break;
9011                 case Q3DEFORM_AUTOSPRITE:
9012                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9013                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9014                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9015                         VectorNormalize(newforward);
9016                         VectorNormalize(newright);
9017                         VectorNormalize(newup);
9018 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9019 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9020 //                      rsurface.batchvertex3f_bufferoffset = 0;
9021 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9022 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9023 //                      rsurface.batchsvector3f_bufferoffset = 0;
9024 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9025 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9026 //                      rsurface.batchtvector3f_bufferoffset = 0;
9027 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9028 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9029 //                      rsurface.batchnormal3f_bufferoffset = 0;
9030                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9031                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9032                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9033                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9034                                 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);
9035                         // a single autosprite surface can contain multiple sprites...
9036                         for (j = 0;j < batchnumvertices - 3;j += 4)
9037                         {
9038                                 VectorClear(center);
9039                                 for (i = 0;i < 4;i++)
9040                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9041                                 VectorScale(center, 0.25f, center);
9042                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9043                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9044                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9045                                 for (i = 0;i < 4;i++)
9046                                 {
9047                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9048                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9049                                 }
9050                         }
9051                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9052                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9053                         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);
9054                         break;
9055                 case Q3DEFORM_AUTOSPRITE2:
9056                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9057                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9058                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9059                         VectorNormalize(newforward);
9060                         VectorNormalize(newright);
9061                         VectorNormalize(newup);
9062 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9063 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9064 //                      rsurface.batchvertex3f_bufferoffset = 0;
9065                         {
9066                                 const float *v1, *v2;
9067                                 vec3_t start, end;
9068                                 float f, l;
9069                                 struct
9070                                 {
9071                                         float length2;
9072                                         const float *v1;
9073                                         const float *v2;
9074                                 }
9075                                 shortest[2];
9076                                 memset(shortest, 0, sizeof(shortest));
9077                                 // a single autosprite surface can contain multiple sprites...
9078                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9079                                 {
9080                                         VectorClear(center);
9081                                         for (i = 0;i < 4;i++)
9082                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9083                                         VectorScale(center, 0.25f, center);
9084                                         // find the two shortest edges, then use them to define the
9085                                         // axis vectors for rotating around the central axis
9086                                         for (i = 0;i < 6;i++)
9087                                         {
9088                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9089                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9090                                                 l = VectorDistance2(v1, v2);
9091                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9092                                                 if (v1[2] != v2[2])
9093                                                         l += (1.0f / 1024.0f);
9094                                                 if (shortest[0].length2 > l || i == 0)
9095                                                 {
9096                                                         shortest[1] = shortest[0];
9097                                                         shortest[0].length2 = l;
9098                                                         shortest[0].v1 = v1;
9099                                                         shortest[0].v2 = v2;
9100                                                 }
9101                                                 else if (shortest[1].length2 > l || i == 1)
9102                                                 {
9103                                                         shortest[1].length2 = l;
9104                                                         shortest[1].v1 = v1;
9105                                                         shortest[1].v2 = v2;
9106                                                 }
9107                                         }
9108                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9109                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9110                                         // this calculates the right vector from the shortest edge
9111                                         // and the up vector from the edge midpoints
9112                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9113                                         VectorNormalize(right);
9114                                         VectorSubtract(end, start, up);
9115                                         VectorNormalize(up);
9116                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9117                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9118                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9119                                         VectorNegate(forward, forward);
9120                                         VectorReflect(forward, 0, up, forward);
9121                                         VectorNormalize(forward);
9122                                         CrossProduct(up, forward, newright);
9123                                         VectorNormalize(newright);
9124                                         // rotate the quad around the up axis vector, this is made
9125                                         // especially easy by the fact we know the quad is flat,
9126                                         // so we only have to subtract the center position and
9127                                         // measure distance along the right vector, and then
9128                                         // multiply that by the newright vector and add back the
9129                                         // center position
9130                                         // we also need to subtract the old position to undo the
9131                                         // displacement from the center, which we do with a
9132                                         // DotProduct, the subtraction/addition of center is also
9133                                         // optimized into DotProducts here
9134                                         l = DotProduct(right, center);
9135                                         for (i = 0;i < 4;i++)
9136                                         {
9137                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9138                                                 f = DotProduct(right, v1) - l;
9139                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9140                                         }
9141                                 }
9142                         }
9143                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9144                         {
9145 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9146 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9147 //                              rsurface.batchnormal3f_bufferoffset = 0;
9148                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9149                         }
9150                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9151                         {
9152 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9153 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9154 //                              rsurface.batchsvector3f_bufferoffset = 0;
9155 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9156 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9157 //                              rsurface.batchtvector3f_bufferoffset = 0;
9158                                 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);
9159                         }
9160                         break;
9161                 case Q3DEFORM_NORMAL:
9162                         // deform the normals to make reflections wavey
9163                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9164                         rsurface.batchnormal3f_vertexbuffer = NULL;
9165                         rsurface.batchnormal3f_bufferoffset = 0;
9166                         for (j = 0;j < batchnumvertices;j++)
9167                         {
9168                                 float vertex[3];
9169                                 float *normal = rsurface.batchnormal3f + 3*j;
9170                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9171                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9172                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9173                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9174                                 VectorNormalize(normal);
9175                         }
9176                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9177                         {
9178 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9179 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9180 //                              rsurface.batchsvector3f_bufferoffset = 0;
9181 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9182 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9183 //                              rsurface.batchtvector3f_bufferoffset = 0;
9184                                 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);
9185                         }
9186                         break;
9187                 case Q3DEFORM_WAVE:
9188                         // deform vertex array to make wavey water and flags and such
9189                         waveparms[0] = deform->waveparms[0];
9190                         waveparms[1] = deform->waveparms[1];
9191                         waveparms[2] = deform->waveparms[2];
9192                         waveparms[3] = deform->waveparms[3];
9193                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9194                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9195                         // this is how a divisor of vertex influence on deformation
9196                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9197                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9198 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9199 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9200 //                      rsurface.batchvertex3f_bufferoffset = 0;
9201 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9202 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9203 //                      rsurface.batchnormal3f_bufferoffset = 0;
9204                         for (j = 0;j < batchnumvertices;j++)
9205                         {
9206                                 // if the wavefunc depends on time, evaluate it per-vertex
9207                                 if (waveparms[3])
9208                                 {
9209                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9210                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9211                                 }
9212                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9213                         }
9214                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9215                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9216                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9217                         {
9218 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9219 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9220 //                              rsurface.batchsvector3f_bufferoffset = 0;
9221 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9222 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9223 //                              rsurface.batchtvector3f_bufferoffset = 0;
9224                                 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);
9225                         }
9226                         break;
9227                 case Q3DEFORM_BULGE:
9228                         // deform vertex array to make the surface have moving bulges
9229 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9230 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9231 //                      rsurface.batchvertex3f_bufferoffset = 0;
9232 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9233 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9234 //                      rsurface.batchnormal3f_bufferoffset = 0;
9235                         for (j = 0;j < batchnumvertices;j++)
9236                         {
9237                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9238                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9239                         }
9240                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9241                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9242                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9243                         {
9244 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9245 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9246 //                              rsurface.batchsvector3f_bufferoffset = 0;
9247 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9248 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9249 //                              rsurface.batchtvector3f_bufferoffset = 0;
9250                                 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);
9251                         }
9252                         break;
9253                 case Q3DEFORM_MOVE:
9254                         // deform vertex array
9255                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9256                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9257                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9258                         VectorScale(deform->parms, scale, waveparms);
9259 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9260 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9261 //                      rsurface.batchvertex3f_bufferoffset = 0;
9262                         for (j = 0;j < batchnumvertices;j++)
9263                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9264                         break;
9265                 }
9266         }
9267
9268         // generate texcoords based on the chosen texcoord source
9269         switch(rsurface.texture->tcgen.tcgen)
9270         {
9271         default:
9272         case Q3TCGEN_TEXTURE:
9273                 break;
9274         case Q3TCGEN_LIGHTMAP:
9275 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9276 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9277 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9278                 if (rsurface.batchtexcoordlightmap2f)
9279                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9280                 break;
9281         case Q3TCGEN_VECTOR:
9282 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9283 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9284 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9285                 for (j = 0;j < batchnumvertices;j++)
9286                 {
9287                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9288                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9289                 }
9290                 break;
9291         case Q3TCGEN_ENVIRONMENT:
9292                 // make environment reflections using a spheremap
9293                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9294                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9295                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9296                 for (j = 0;j < batchnumvertices;j++)
9297                 {
9298                         // identical to Q3A's method, but executed in worldspace so
9299                         // carried models can be shiny too
9300
9301                         float viewer[3], d, reflected[3], worldreflected[3];
9302
9303                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9304                         // VectorNormalize(viewer);
9305
9306                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9307
9308                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9309                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9310                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9311                         // note: this is proportinal to viewer, so we can normalize later
9312
9313                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9314                         VectorNormalize(worldreflected);
9315
9316                         // note: this sphere map only uses world x and z!
9317                         // so positive and negative y will LOOK THE SAME.
9318                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9319                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9320                 }
9321                 break;
9322         }
9323         // the only tcmod that needs software vertex processing is turbulent, so
9324         // check for it here and apply the changes if needed
9325         // and we only support that as the first one
9326         // (handling a mixture of turbulent and other tcmods would be problematic
9327         //  without punting it entirely to a software path)
9328         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9329         {
9330                 amplitude = rsurface.texture->tcmods[0].parms[1];
9331                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9332 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9333 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9334 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9335                 for (j = 0;j < batchnumvertices;j++)
9336                 {
9337                         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);
9338                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9339                 }
9340         }
9341
9342         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9343         {
9344                 // convert the modified arrays to vertex structs
9345 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9346 //              rsurface.batchvertexmeshbuffer = NULL;
9347                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9348                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9349                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9350                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9351                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9352                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9353                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9354                 {
9355                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9356                         {
9357                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9358                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9359                         }
9360                 }
9361                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9362                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9363                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9364                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9365                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9366                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9367                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9368                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9369                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9370         }
9371 }
9372
9373 void RSurf_DrawBatch(void)
9374 {
9375         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9376         // through the pipeline, killing it earlier in the pipeline would have
9377         // per-surface overhead rather than per-batch overhead, so it's best to
9378         // reject it here, before it hits glDraw.
9379         if (rsurface.batchnumtriangles == 0)
9380                 return;
9381 #if 0
9382         // batch debugging code
9383         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9384         {
9385                 int i;
9386                 int j;
9387                 int c;
9388                 const int *e;
9389                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9390                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9391                 {
9392                         c = e[i];
9393                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9394                         {
9395                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9396                                 {
9397                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9398                                                 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);
9399                                         break;
9400                                 }
9401                         }
9402                 }
9403         }
9404 #endif
9405         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);
9406 }
9407
9408 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9409 {
9410         // pick the closest matching water plane
9411         int planeindex, vertexindex, bestplaneindex = -1;
9412         float d, bestd;
9413         vec3_t vert;
9414         const float *v;
9415         r_waterstate_waterplane_t *p;
9416         qboolean prepared = false;
9417         bestd = 0;
9418         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9419         {
9420                 if(p->camera_entity != rsurface.texture->camera_entity)
9421                         continue;
9422                 d = 0;
9423                 if(!prepared)
9424                 {
9425                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9426                         prepared = true;
9427                         if(rsurface.batchnumvertices == 0)
9428                                 break;
9429                 }
9430                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9431                 {
9432                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9433                         d += fabs(PlaneDiff(vert, &p->plane));
9434                 }
9435                 if (bestd > d || bestplaneindex < 0)
9436                 {
9437                         bestd = d;
9438                         bestplaneindex = planeindex;
9439                 }
9440         }
9441         return bestplaneindex;
9442         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9443         // this situation though, as it might be better to render single larger
9444         // batches with useless stuff (backface culled for example) than to
9445         // render multiple smaller batches
9446 }
9447
9448 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9449 {
9450         int i;
9451         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9452         rsurface.passcolor4f_vertexbuffer = 0;
9453         rsurface.passcolor4f_bufferoffset = 0;
9454         for (i = 0;i < rsurface.batchnumvertices;i++)
9455                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9456 }
9457
9458 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9459 {
9460         int i;
9461         float f;
9462         const float *v;
9463         const float *c;
9464         float *c2;
9465         if (rsurface.passcolor4f)
9466         {
9467                 // generate color arrays
9468                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9469                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9470                 rsurface.passcolor4f_vertexbuffer = 0;
9471                 rsurface.passcolor4f_bufferoffset = 0;
9472                 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)
9473                 {
9474                         f = RSurf_FogVertex(v);
9475                         c2[0] = c[0] * f;
9476                         c2[1] = c[1] * f;
9477                         c2[2] = c[2] * f;
9478                         c2[3] = c[3];
9479                 }
9480         }
9481         else
9482         {
9483                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9484                 rsurface.passcolor4f_vertexbuffer = 0;
9485                 rsurface.passcolor4f_bufferoffset = 0;
9486                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9487                 {
9488                         f = RSurf_FogVertex(v);
9489                         c2[0] = f;
9490                         c2[1] = f;
9491                         c2[2] = f;
9492                         c2[3] = 1;
9493                 }
9494         }
9495 }
9496
9497 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9498 {
9499         int i;
9500         float f;
9501         const float *v;
9502         const float *c;
9503         float *c2;
9504         if (!rsurface.passcolor4f)
9505                 return;
9506         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9507         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9508         rsurface.passcolor4f_vertexbuffer = 0;
9509         rsurface.passcolor4f_bufferoffset = 0;
9510         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9511         {
9512                 f = RSurf_FogVertex(v);
9513                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9514                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9515                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9516                 c2[3] = c[3];
9517         }
9518 }
9519
9520 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
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;
9534                 c2[1] = c[1] * g;
9535                 c2[2] = c[2] * b;
9536                 c2[3] = c[3] * a;
9537         }
9538 }
9539
9540 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9541 {
9542         int i;
9543         const float *c;
9544         float *c2;
9545         if (!rsurface.passcolor4f)
9546                 return;
9547         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9548         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9549         rsurface.passcolor4f_vertexbuffer = 0;
9550         rsurface.passcolor4f_bufferoffset = 0;
9551         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9552         {
9553                 c2[0] = c[0] + r_refdef.scene.ambient;
9554                 c2[1] = c[1] + r_refdef.scene.ambient;
9555                 c2[2] = c[2] + r_refdef.scene.ambient;
9556                 c2[3] = c[3];
9557         }
9558 }
9559
9560 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9561 {
9562         // TODO: optimize
9563         rsurface.passcolor4f = NULL;
9564         rsurface.passcolor4f_vertexbuffer = 0;
9565         rsurface.passcolor4f_bufferoffset = 0;
9566         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9567         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9568         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9569         GL_Color(r, g, b, a);
9570         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9571         RSurf_DrawBatch();
9572 }
9573
9574 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9575 {
9576         // TODO: optimize applyfog && applycolor case
9577         // just apply fog if necessary, and tint the fog color array if necessary
9578         rsurface.passcolor4f = NULL;
9579         rsurface.passcolor4f_vertexbuffer = 0;
9580         rsurface.passcolor4f_bufferoffset = 0;
9581         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9582         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9583         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9584         GL_Color(r, g, b, a);
9585         RSurf_DrawBatch();
9586 }
9587
9588 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9589 {
9590         // TODO: optimize
9591         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9592         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9593         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9594         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9595         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9596         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9597         GL_Color(r, g, b, a);
9598         RSurf_DrawBatch();
9599 }
9600
9601 static void RSurf_DrawBatch_GL11_ClampColor(void)
9602 {
9603         int i;
9604         const float *c1;
9605         float *c2;
9606         if (!rsurface.passcolor4f)
9607                 return;
9608         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9609         {
9610                 c2[0] = bound(0.0f, c1[0], 1.0f);
9611                 c2[1] = bound(0.0f, c1[1], 1.0f);
9612                 c2[2] = bound(0.0f, c1[2], 1.0f);
9613                 c2[3] = bound(0.0f, c1[3], 1.0f);
9614         }
9615 }
9616
9617 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9618 {
9619         int i;
9620         float f;
9621         const float *v;
9622         const float *n;
9623         float *c;
9624         //vec3_t eyedir;
9625
9626         // fake shading
9627         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9628         rsurface.passcolor4f_vertexbuffer = 0;
9629         rsurface.passcolor4f_bufferoffset = 0;
9630         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)
9631         {
9632                 f = -DotProduct(r_refdef.view.forward, n);
9633                 f = max(0, f);
9634                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9635                 f *= r_refdef.lightmapintensity;
9636                 Vector4Set(c, f, f, f, 1);
9637         }
9638 }
9639
9640 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9641 {
9642         RSurf_DrawBatch_GL11_ApplyFakeLight();
9643         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9644         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9645         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9646         GL_Color(r, g, b, a);
9647         RSurf_DrawBatch();
9648 }
9649
9650 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9651 {
9652         int i;
9653         float f;
9654         float alpha;
9655         const float *v;
9656         const float *n;
9657         float *c;
9658         vec3_t ambientcolor;
9659         vec3_t diffusecolor;
9660         vec3_t lightdir;
9661         // TODO: optimize
9662         // model lighting
9663         VectorCopy(rsurface.modellight_lightdir, lightdir);
9664         f = 0.5f * r_refdef.lightmapintensity;
9665         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9666         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9667         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9668         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9669         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9670         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9671         alpha = *a;
9672         if (VectorLength2(diffusecolor) > 0)
9673         {
9674                 // q3-style directional shading
9675                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9676                 rsurface.passcolor4f_vertexbuffer = 0;
9677                 rsurface.passcolor4f_bufferoffset = 0;
9678                 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)
9679                 {
9680                         if ((f = DotProduct(n, lightdir)) > 0)
9681                                 VectorMA(ambientcolor, f, diffusecolor, c);
9682                         else
9683                                 VectorCopy(ambientcolor, c);
9684                         c[3] = alpha;
9685                 }
9686                 *r = 1;
9687                 *g = 1;
9688                 *b = 1;
9689                 *a = 1;
9690                 *applycolor = false;
9691         }
9692         else
9693         {
9694                 *r = ambientcolor[0];
9695                 *g = ambientcolor[1];
9696                 *b = ambientcolor[2];
9697                 rsurface.passcolor4f = NULL;
9698                 rsurface.passcolor4f_vertexbuffer = 0;
9699                 rsurface.passcolor4f_bufferoffset = 0;
9700         }
9701 }
9702
9703 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9704 {
9705         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9706         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9707         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9708         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9709         GL_Color(r, g, b, a);
9710         RSurf_DrawBatch();
9711 }
9712
9713 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9714 {
9715         int i;
9716         float f;
9717         const float *v;
9718         float *c;
9719
9720         // fake shading
9721         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9722         rsurface.passcolor4f_vertexbuffer = 0;
9723         rsurface.passcolor4f_bufferoffset = 0;
9724
9725         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9726         {
9727                 f = 1 - RSurf_FogVertex(v);
9728                 c[0] = r;
9729                 c[1] = g;
9730                 c[2] = b;
9731                 c[3] = f * a;
9732         }
9733 }
9734
9735 void RSurf_SetupDepthAndCulling(void)
9736 {
9737         // submodels are biased to avoid z-fighting with world surfaces that they
9738         // may be exactly overlapping (avoids z-fighting artifacts on certain
9739         // doors and things in Quake maps)
9740         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9741         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9742         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9743         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9744 }
9745
9746 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9747 {
9748         // transparent sky would be ridiculous
9749         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9750                 return;
9751         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9752         skyrenderlater = true;
9753         RSurf_SetupDepthAndCulling();
9754         GL_DepthMask(true);
9755         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9756         // skymasking on them, and Quake3 never did sky masking (unlike
9757         // software Quake and software Quake2), so disable the sky masking
9758         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9759         // and skymasking also looks very bad when noclipping outside the
9760         // level, so don't use it then either.
9761         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9762         {
9763                 R_Mesh_ResetTextureState();
9764                 if (skyrendermasked)
9765                 {
9766                         R_SetupShader_DepthOrShadow(false);
9767                         // depth-only (masking)
9768                         GL_ColorMask(0,0,0,0);
9769                         // just to make sure that braindead drivers don't draw
9770                         // anything despite that colormask...
9771                         GL_BlendFunc(GL_ZERO, GL_ONE);
9772                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9773                         if (rsurface.batchvertex3fbuffer)
9774                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9775                         else
9776                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9777                 }
9778                 else
9779                 {
9780                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9781                         // fog sky
9782                         GL_BlendFunc(GL_ONE, GL_ZERO);
9783                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9784                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9785                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9786                 }
9787                 RSurf_DrawBatch();
9788                 if (skyrendermasked)
9789                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9790         }
9791         R_Mesh_ResetTextureState();
9792         GL_Color(1, 1, 1, 1);
9793 }
9794
9795 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9796 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9797 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9798 {
9799         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9800                 return;
9801         if (prepass)
9802         {
9803                 // render screenspace normalmap to texture
9804                 GL_DepthMask(true);
9805                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9806                 RSurf_DrawBatch();
9807         }
9808
9809         // bind lightmap texture
9810
9811         // water/refraction/reflection/camera surfaces have to be handled specially
9812         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9813         {
9814                 int start, end, startplaneindex;
9815                 for (start = 0;start < texturenumsurfaces;start = end)
9816                 {
9817                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9818                         if(startplaneindex < 0)
9819                         {
9820                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9821                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9822                                 end = start + 1;
9823                                 continue;
9824                         }
9825                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9826                                 ;
9827                         // now that we have a batch using the same planeindex, render it
9828                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9829                         {
9830                                 // render water or distortion background
9831                                 GL_DepthMask(true);
9832                                 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);
9833                                 RSurf_DrawBatch();
9834                                 // blend surface on top
9835                                 GL_DepthMask(false);
9836                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9837                                 RSurf_DrawBatch();
9838                         }
9839                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9840                         {
9841                                 // render surface with reflection texture as input
9842                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9843                                 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);
9844                                 RSurf_DrawBatch();
9845                         }
9846                 }
9847                 return;
9848         }
9849
9850         // render surface batch normally
9851         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9852         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);
9853         RSurf_DrawBatch();
9854 }
9855
9856 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9857 {
9858         // OpenGL 1.3 path - anything not completely ancient
9859         qboolean applycolor;
9860         qboolean applyfog;
9861         int layerindex;
9862         const texturelayer_t *layer;
9863         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);
9864         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9865
9866         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9867         {
9868                 vec4_t layercolor;
9869                 int layertexrgbscale;
9870                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9871                 {
9872                         if (layerindex == 0)
9873                                 GL_AlphaTest(true);
9874                         else
9875                         {
9876                                 GL_AlphaTest(false);
9877                                 GL_DepthFunc(GL_EQUAL);
9878                         }
9879                 }
9880                 GL_DepthMask(layer->depthmask && writedepth);
9881                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9882                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9883                 {
9884                         layertexrgbscale = 4;
9885                         VectorScale(layer->color, 0.25f, layercolor);
9886                 }
9887                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9888                 {
9889                         layertexrgbscale = 2;
9890                         VectorScale(layer->color, 0.5f, layercolor);
9891                 }
9892                 else
9893                 {
9894                         layertexrgbscale = 1;
9895                         VectorScale(layer->color, 1.0f, layercolor);
9896                 }
9897                 layercolor[3] = layer->color[3];
9898                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9899                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9900                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9901                 switch (layer->type)
9902                 {
9903                 case TEXTURELAYERTYPE_LITTEXTURE:
9904                         // single-pass lightmapped texture with 2x rgbscale
9905                         R_Mesh_TexBind(0, r_texture_white);
9906                         R_Mesh_TexMatrix(0, NULL);
9907                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9908                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9909                         R_Mesh_TexBind(1, layer->texture);
9910                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9911                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9912                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9913                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9914                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9915                         else if (FAKELIGHT_ENABLED)
9916                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9917                         else if (rsurface.uselightmaptexture)
9918                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9919                         else
9920                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9921                         break;
9922                 case TEXTURELAYERTYPE_TEXTURE:
9923                         // singletexture unlit texture with transparency support
9924                         R_Mesh_TexBind(0, layer->texture);
9925                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9926                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9927                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9928                         R_Mesh_TexBind(1, 0);
9929                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9930                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9931                         break;
9932                 case TEXTURELAYERTYPE_FOG:
9933                         // singletexture fogging
9934                         if (layer->texture)
9935                         {
9936                                 R_Mesh_TexBind(0, layer->texture);
9937                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9938                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9939                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9940                         }
9941                         else
9942                         {
9943                                 R_Mesh_TexBind(0, 0);
9944                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9945                         }
9946                         R_Mesh_TexBind(1, 0);
9947                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9948                         // generate a color array for the fog pass
9949                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9950                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9951                         RSurf_DrawBatch();
9952                         break;
9953                 default:
9954                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9955                 }
9956         }
9957         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9958         {
9959                 GL_DepthFunc(GL_LEQUAL);
9960                 GL_AlphaTest(false);
9961         }
9962 }
9963
9964 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9965 {
9966         // OpenGL 1.1 - crusty old voodoo path
9967         qboolean applyfog;
9968         int layerindex;
9969         const texturelayer_t *layer;
9970         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);
9971         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9972
9973         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9974         {
9975                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9976                 {
9977                         if (layerindex == 0)
9978                                 GL_AlphaTest(true);
9979                         else
9980                         {
9981                                 GL_AlphaTest(false);
9982                                 GL_DepthFunc(GL_EQUAL);
9983                         }
9984                 }
9985                 GL_DepthMask(layer->depthmask && writedepth);
9986                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9987                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9988                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9989                 switch (layer->type)
9990                 {
9991                 case TEXTURELAYERTYPE_LITTEXTURE:
9992                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9993                         {
9994                                 // two-pass lit texture with 2x rgbscale
9995                                 // first the lightmap pass
9996                                 R_Mesh_TexBind(0, r_texture_white);
9997                                 R_Mesh_TexMatrix(0, NULL);
9998                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9999                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10000                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10001                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10002                                 else if (FAKELIGHT_ENABLED)
10003                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10004                                 else if (rsurface.uselightmaptexture)
10005                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10006                                 else
10007                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10008                                 // then apply the texture to it
10009                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10010                                 R_Mesh_TexBind(0, layer->texture);
10011                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10012                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10013                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10014                                 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);
10015                         }
10016                         else
10017                         {
10018                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10019                                 R_Mesh_TexBind(0, layer->texture);
10020                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10021                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10022                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10023                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10024                                         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);
10025                                 else
10026                                         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);
10027                         }
10028                         break;
10029                 case TEXTURELAYERTYPE_TEXTURE:
10030                         // singletexture unlit texture with transparency support
10031                         R_Mesh_TexBind(0, layer->texture);
10032                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10033                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10034                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10035                         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);
10036                         break;
10037                 case TEXTURELAYERTYPE_FOG:
10038                         // singletexture fogging
10039                         if (layer->texture)
10040                         {
10041                                 R_Mesh_TexBind(0, layer->texture);
10042                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10043                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10044                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10045                         }
10046                         else
10047                         {
10048                                 R_Mesh_TexBind(0, 0);
10049                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10050                         }
10051                         // generate a color array for the fog pass
10052                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10053                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10054                         RSurf_DrawBatch();
10055                         break;
10056                 default:
10057                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10058                 }
10059         }
10060         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10061         {
10062                 GL_DepthFunc(GL_LEQUAL);
10063                 GL_AlphaTest(false);
10064         }
10065 }
10066
10067 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10068 {
10069         int vi;
10070         int j;
10071         r_vertexgeneric_t *batchvertex;
10072         float c[4];
10073
10074 //      R_Mesh_ResetTextureState();
10075         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10076
10077         if(rsurface.texture && rsurface.texture->currentskinframe)
10078         {
10079                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10080                 c[3] *= rsurface.texture->currentalpha;
10081         }
10082         else
10083         {
10084                 c[0] = 1;
10085                 c[1] = 0;
10086                 c[2] = 1;
10087                 c[3] = 1;
10088         }
10089
10090         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10091         {
10092                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10093                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10094                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10095         }
10096
10097         // brighten it up (as texture value 127 means "unlit")
10098         c[0] *= 2 * r_refdef.view.colorscale;
10099         c[1] *= 2 * r_refdef.view.colorscale;
10100         c[2] *= 2 * r_refdef.view.colorscale;
10101
10102         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10103                 c[3] *= r_wateralpha.value;
10104
10105         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10106         {
10107                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10108                 GL_DepthMask(false);
10109         }
10110         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10111         {
10112                 GL_BlendFunc(GL_ONE, GL_ONE);
10113                 GL_DepthMask(false);
10114         }
10115         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10116         {
10117                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10118                 GL_DepthMask(false);
10119         }
10120         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10121         {
10122                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10123                 GL_DepthMask(false);
10124         }
10125         else
10126         {
10127                 GL_BlendFunc(GL_ONE, GL_ZERO);
10128                 GL_DepthMask(writedepth);
10129         }
10130
10131         if (r_showsurfaces.integer == 3)
10132         {
10133                 rsurface.passcolor4f = NULL;
10134
10135                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10136                 {
10137                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10138
10139                         rsurface.passcolor4f = NULL;
10140                         rsurface.passcolor4f_vertexbuffer = 0;
10141                         rsurface.passcolor4f_bufferoffset = 0;
10142                 }
10143                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10144                 {
10145                         qboolean applycolor = true;
10146                         float one = 1.0;
10147
10148                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10149
10150                         r_refdef.lightmapintensity = 1;
10151                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10152                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10153                 }
10154                 else if (FAKELIGHT_ENABLED)
10155                 {
10156                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10157
10158                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10159                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10160                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10161                 }
10162                 else
10163                 {
10164                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10165
10166                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10167                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10168                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10169                 }
10170
10171                 if(!rsurface.passcolor4f)
10172                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10173
10174                 RSurf_DrawBatch_GL11_ApplyAmbient();
10175                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10176                 if(r_refdef.fogenabled)
10177                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10178                 RSurf_DrawBatch_GL11_ClampColor();
10179
10180                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10181                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10182                 RSurf_DrawBatch();
10183         }
10184         else if (!r_refdef.view.showdebug)
10185         {
10186                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10187                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10188                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10189                 {
10190                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10191                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10192                 }
10193                 R_Mesh_PrepareVertices_Generic_Unlock();
10194                 RSurf_DrawBatch();
10195         }
10196         else if (r_showsurfaces.integer == 4)
10197         {
10198                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10199                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10200                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10201                 {
10202                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10203                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10204                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10205                 }
10206                 R_Mesh_PrepareVertices_Generic_Unlock();
10207                 RSurf_DrawBatch();
10208         }
10209         else if (r_showsurfaces.integer == 2)
10210         {
10211                 const int *e;
10212                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10213                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10214                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10215                 {
10216                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10217                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10218                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10219                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10220                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10221                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10222                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10223                 }
10224                 R_Mesh_PrepareVertices_Generic_Unlock();
10225                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10226         }
10227         else
10228         {
10229                 int texturesurfaceindex;
10230                 int k;
10231                 const msurface_t *surface;
10232                 float surfacecolor4f[4];
10233                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10234                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10235                 vi = 0;
10236                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10237                 {
10238                         surface = texturesurfacelist[texturesurfaceindex];
10239                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10240                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10241                         for (j = 0;j < surface->num_vertices;j++)
10242                         {
10243                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10244                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10245                                 vi++;
10246                         }
10247                 }
10248                 R_Mesh_PrepareVertices_Generic_Unlock();
10249                 RSurf_DrawBatch();
10250         }
10251 }
10252
10253 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10254 {
10255         CHECKGLERROR
10256         RSurf_SetupDepthAndCulling();
10257         if (r_showsurfaces.integer)
10258         {
10259                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10260                 return;
10261         }
10262         switch (vid.renderpath)
10263         {
10264         case RENDERPATH_GL20:
10265         case RENDERPATH_D3D9:
10266         case RENDERPATH_D3D10:
10267         case RENDERPATH_D3D11:
10268         case RENDERPATH_SOFT:
10269         case RENDERPATH_GLES2:
10270                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10271                 break;
10272         case RENDERPATH_GL13:
10273         case RENDERPATH_GLES1:
10274                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10275                 break;
10276         case RENDERPATH_GL11:
10277                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10278                 break;
10279         }
10280         CHECKGLERROR
10281 }
10282
10283 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10284 {
10285         CHECKGLERROR
10286         RSurf_SetupDepthAndCulling();
10287         if (r_showsurfaces.integer)
10288         {
10289                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10290                 return;
10291         }
10292         switch (vid.renderpath)
10293         {
10294         case RENDERPATH_GL20:
10295         case RENDERPATH_D3D9:
10296         case RENDERPATH_D3D10:
10297         case RENDERPATH_D3D11:
10298         case RENDERPATH_SOFT:
10299         case RENDERPATH_GLES2:
10300                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10301                 break;
10302         case RENDERPATH_GL13:
10303         case RENDERPATH_GLES1:
10304                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10305                 break;
10306         case RENDERPATH_GL11:
10307                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10308                 break;
10309         }
10310         CHECKGLERROR
10311 }
10312
10313 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10314 {
10315         int i, j;
10316         int texturenumsurfaces, endsurface;
10317         texture_t *texture;
10318         const msurface_t *surface;
10319         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10320
10321         // if the model is static it doesn't matter what value we give for
10322         // wantnormals and wanttangents, so this logic uses only rules applicable
10323         // to a model, knowing that they are meaningless otherwise
10324         if (ent == r_refdef.scene.worldentity)
10325                 RSurf_ActiveWorldEntity();
10326         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10327                 RSurf_ActiveModelEntity(ent, false, false, false);
10328         else
10329         {
10330                 switch (vid.renderpath)
10331                 {
10332                 case RENDERPATH_GL20:
10333                 case RENDERPATH_D3D9:
10334                 case RENDERPATH_D3D10:
10335                 case RENDERPATH_D3D11:
10336                 case RENDERPATH_SOFT:
10337                 case RENDERPATH_GLES2:
10338                         RSurf_ActiveModelEntity(ent, true, true, false);
10339                         break;
10340                 case RENDERPATH_GL11:
10341                 case RENDERPATH_GL13:
10342                 case RENDERPATH_GLES1:
10343                         RSurf_ActiveModelEntity(ent, true, false, false);
10344                         break;
10345                 }
10346         }
10347
10348         if (r_transparentdepthmasking.integer)
10349         {
10350                 qboolean setup = false;
10351                 for (i = 0;i < numsurfaces;i = j)
10352                 {
10353                         j = i + 1;
10354                         surface = rsurface.modelsurfaces + surfacelist[i];
10355                         texture = surface->texture;
10356                         rsurface.texture = R_GetCurrentTexture(texture);
10357                         rsurface.lightmaptexture = NULL;
10358                         rsurface.deluxemaptexture = NULL;
10359                         rsurface.uselightmaptexture = false;
10360                         // scan ahead until we find a different texture
10361                         endsurface = min(i + 1024, numsurfaces);
10362                         texturenumsurfaces = 0;
10363                         texturesurfacelist[texturenumsurfaces++] = surface;
10364                         for (;j < endsurface;j++)
10365                         {
10366                                 surface = rsurface.modelsurfaces + surfacelist[j];
10367                                 if (texture != surface->texture)
10368                                         break;
10369                                 texturesurfacelist[texturenumsurfaces++] = surface;
10370                         }
10371                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10372                                 continue;
10373                         // render the range of surfaces as depth
10374                         if (!setup)
10375                         {
10376                                 setup = true;
10377                                 GL_ColorMask(0,0,0,0);
10378                                 GL_Color(1,1,1,1);
10379                                 GL_DepthTest(true);
10380                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10381                                 GL_DepthMask(true);
10382 //                              R_Mesh_ResetTextureState();
10383                                 R_SetupShader_DepthOrShadow(false);
10384                         }
10385                         RSurf_SetupDepthAndCulling();
10386                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10387                         if (rsurface.batchvertex3fbuffer)
10388                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10389                         else
10390                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10391                         RSurf_DrawBatch();
10392                 }
10393                 if (setup)
10394                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10395         }
10396
10397         for (i = 0;i < numsurfaces;i = j)
10398         {
10399                 j = i + 1;
10400                 surface = rsurface.modelsurfaces + surfacelist[i];
10401                 texture = surface->texture;
10402                 rsurface.texture = R_GetCurrentTexture(texture);
10403                 // scan ahead until we find a different texture
10404                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10405                 texturenumsurfaces = 0;
10406                 texturesurfacelist[texturenumsurfaces++] = surface;
10407                 if(FAKELIGHT_ENABLED)
10408                 {
10409                         rsurface.lightmaptexture = NULL;
10410                         rsurface.deluxemaptexture = NULL;
10411                         rsurface.uselightmaptexture = false;
10412                         for (;j < endsurface;j++)
10413                         {
10414                                 surface = rsurface.modelsurfaces + surfacelist[j];
10415                                 if (texture != surface->texture)
10416                                         break;
10417                                 texturesurfacelist[texturenumsurfaces++] = surface;
10418                         }
10419                 }
10420                 else
10421                 {
10422                         rsurface.lightmaptexture = surface->lightmaptexture;
10423                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10424                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10425                         for (;j < endsurface;j++)
10426                         {
10427                                 surface = rsurface.modelsurfaces + surfacelist[j];
10428                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10429                                         break;
10430                                 texturesurfacelist[texturenumsurfaces++] = surface;
10431                         }
10432                 }
10433                 // render the range of surfaces
10434                 if (ent == r_refdef.scene.worldentity)
10435                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10436                 else
10437                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10438         }
10439         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10440 }
10441
10442 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10443 {
10444         // transparent surfaces get pushed off into the transparent queue
10445         int surfacelistindex;
10446         const msurface_t *surface;
10447         vec3_t tempcenter, center;
10448         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10449         {
10450                 surface = texturesurfacelist[surfacelistindex];
10451                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10452                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10453                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10454                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10455                 if (queueentity->transparent_offset) // transparent offset
10456                 {
10457                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10458                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10459                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10460                 }
10461                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10462         }
10463 }
10464
10465 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10466 {
10467         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10468                 return;
10469         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10470                 return;
10471         RSurf_SetupDepthAndCulling();
10472         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10473         if (rsurface.batchvertex3fbuffer)
10474                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10475         else
10476                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10477         RSurf_DrawBatch();
10478 }
10479
10480 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10481 {
10482         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10483         CHECKGLERROR
10484         if (depthonly)
10485                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10486         else if (prepass)
10487         {
10488                 if (!rsurface.texture->currentnumlayers)
10489                         return;
10490                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10491                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10492                 else
10493                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10494         }
10495         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10496                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10497         else if (!rsurface.texture->currentnumlayers)
10498                 return;
10499         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10500         {
10501                 // in the deferred case, transparent surfaces were queued during prepass
10502                 if (!r_shadow_usingdeferredprepass)
10503                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10504         }
10505         else
10506         {
10507                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10508                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10509         }
10510         CHECKGLERROR
10511 }
10512
10513 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10514 {
10515         int i, j;
10516         texture_t *texture;
10517         R_FrameData_SetMark();
10518         // break the surface list down into batches by texture and use of lightmapping
10519         for (i = 0;i < numsurfaces;i = j)
10520         {
10521                 j = i + 1;
10522                 // texture is the base texture pointer, rsurface.texture is the
10523                 // current frame/skin the texture is directing us to use (for example
10524                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10525                 // use skin 1 instead)
10526                 texture = surfacelist[i]->texture;
10527                 rsurface.texture = R_GetCurrentTexture(texture);
10528                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10529                 {
10530                         // if this texture is not the kind we want, skip ahead to the next one
10531                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10532                                 ;
10533                         continue;
10534                 }
10535                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10536                 {
10537                         rsurface.lightmaptexture = NULL;
10538                         rsurface.deluxemaptexture = NULL;
10539                         rsurface.uselightmaptexture = false;
10540                         // simply scan ahead until we find a different texture or lightmap state
10541                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10542                                 ;
10543                 }
10544                 else
10545                 {
10546                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10547                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10548                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10549                         // simply scan ahead until we find a different texture or lightmap state
10550                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10551                                 ;
10552                 }
10553                 // render the range of surfaces
10554                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10555         }
10556         R_FrameData_ReturnToMark();
10557 }
10558
10559 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10560 {
10561         CHECKGLERROR
10562         if (depthonly)
10563                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10564         else if (prepass)
10565         {
10566                 if (!rsurface.texture->currentnumlayers)
10567                         return;
10568                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10569                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10570                 else
10571                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10572         }
10573         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10574                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10575         else if (!rsurface.texture->currentnumlayers)
10576                 return;
10577         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10578         {
10579                 // in the deferred case, transparent surfaces were queued during prepass
10580                 if (!r_shadow_usingdeferredprepass)
10581                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10582         }
10583         else
10584         {
10585                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10586                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10587         }
10588         CHECKGLERROR
10589 }
10590
10591 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10592 {
10593         int i, j;
10594         texture_t *texture;
10595         R_FrameData_SetMark();
10596         // break the surface list down into batches by texture and use of lightmapping
10597         for (i = 0;i < numsurfaces;i = j)
10598         {
10599                 j = i + 1;
10600                 // texture is the base texture pointer, rsurface.texture is the
10601                 // current frame/skin the texture is directing us to use (for example
10602                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10603                 // use skin 1 instead)
10604                 texture = surfacelist[i]->texture;
10605                 rsurface.texture = R_GetCurrentTexture(texture);
10606                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10607                 {
10608                         // if this texture is not the kind we want, skip ahead to the next one
10609                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10610                                 ;
10611                         continue;
10612                 }
10613                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10614                 {
10615                         rsurface.lightmaptexture = NULL;
10616                         rsurface.deluxemaptexture = NULL;
10617                         rsurface.uselightmaptexture = false;
10618                         // simply scan ahead until we find a different texture or lightmap state
10619                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10620                                 ;
10621                 }
10622                 else
10623                 {
10624                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10625                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10626                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10627                         // simply scan ahead until we find a different texture or lightmap state
10628                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10629                                 ;
10630                 }
10631                 // render the range of surfaces
10632                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10633         }
10634         R_FrameData_ReturnToMark();
10635 }
10636
10637 float locboxvertex3f[6*4*3] =
10638 {
10639         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10640         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10641         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10642         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10643         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10644         1,0,0, 0,0,0, 0,1,0, 1,1,0
10645 };
10646
10647 unsigned short locboxelements[6*2*3] =
10648 {
10649          0, 1, 2, 0, 2, 3,
10650          4, 5, 6, 4, 6, 7,
10651          8, 9,10, 8,10,11,
10652         12,13,14, 12,14,15,
10653         16,17,18, 16,18,19,
10654         20,21,22, 20,22,23
10655 };
10656
10657 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10658 {
10659         int i, j;
10660         cl_locnode_t *loc = (cl_locnode_t *)ent;
10661         vec3_t mins, size;
10662         float vertex3f[6*4*3];
10663         CHECKGLERROR
10664         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10665         GL_DepthMask(false);
10666         GL_DepthRange(0, 1);
10667         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10668         GL_DepthTest(true);
10669         GL_CullFace(GL_NONE);
10670         R_EntityMatrix(&identitymatrix);
10671
10672 //      R_Mesh_ResetTextureState();
10673
10674         i = surfacelist[0];
10675         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10676                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10677                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10678                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10679
10680         if (VectorCompare(loc->mins, loc->maxs))
10681         {
10682                 VectorSet(size, 2, 2, 2);
10683                 VectorMA(loc->mins, -0.5f, size, mins);
10684         }
10685         else
10686         {
10687                 VectorCopy(loc->mins, mins);
10688                 VectorSubtract(loc->maxs, loc->mins, size);
10689         }
10690
10691         for (i = 0;i < 6*4*3;)
10692                 for (j = 0;j < 3;j++, i++)
10693                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10694
10695         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10696         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10697         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10698 }
10699
10700 void R_DrawLocs(void)
10701 {
10702         int index;
10703         cl_locnode_t *loc, *nearestloc;
10704         vec3_t center;
10705         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10706         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10707         {
10708                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10709                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10710         }
10711 }
10712
10713 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10714 {
10715         if (decalsystem->decals)
10716                 Mem_Free(decalsystem->decals);
10717         memset(decalsystem, 0, sizeof(*decalsystem));
10718 }
10719
10720 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)
10721 {
10722         tridecal_t *decal;
10723         tridecal_t *decals;
10724         int i;
10725
10726         // expand or initialize the system
10727         if (decalsystem->maxdecals <= decalsystem->numdecals)
10728         {
10729                 decalsystem_t old = *decalsystem;
10730                 qboolean useshortelements;
10731                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10732                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10733                 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)));
10734                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10735                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10736                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10737                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10738                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10739                 if (decalsystem->numdecals)
10740                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10741                 if (old.decals)
10742                         Mem_Free(old.decals);
10743                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10744                         decalsystem->element3i[i] = i;
10745                 if (useshortelements)
10746                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10747                                 decalsystem->element3s[i] = i;
10748         }
10749
10750         // grab a decal and search for another free slot for the next one
10751         decals = decalsystem->decals;
10752         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10753         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10754                 ;
10755         decalsystem->freedecal = i;
10756         if (decalsystem->numdecals <= i)
10757                 decalsystem->numdecals = i + 1;
10758
10759         // initialize the decal
10760         decal->lived = 0;
10761         decal->triangleindex = triangleindex;
10762         decal->surfaceindex = surfaceindex;
10763         decal->decalsequence = decalsequence;
10764         decal->color4f[0][0] = c0[0];
10765         decal->color4f[0][1] = c0[1];
10766         decal->color4f[0][2] = c0[2];
10767         decal->color4f[0][3] = 1;
10768         decal->color4f[1][0] = c1[0];
10769         decal->color4f[1][1] = c1[1];
10770         decal->color4f[1][2] = c1[2];
10771         decal->color4f[1][3] = 1;
10772         decal->color4f[2][0] = c2[0];
10773         decal->color4f[2][1] = c2[1];
10774         decal->color4f[2][2] = c2[2];
10775         decal->color4f[2][3] = 1;
10776         decal->vertex3f[0][0] = v0[0];
10777         decal->vertex3f[0][1] = v0[1];
10778         decal->vertex3f[0][2] = v0[2];
10779         decal->vertex3f[1][0] = v1[0];
10780         decal->vertex3f[1][1] = v1[1];
10781         decal->vertex3f[1][2] = v1[2];
10782         decal->vertex3f[2][0] = v2[0];
10783         decal->vertex3f[2][1] = v2[1];
10784         decal->vertex3f[2][2] = v2[2];
10785         decal->texcoord2f[0][0] = t0[0];
10786         decal->texcoord2f[0][1] = t0[1];
10787         decal->texcoord2f[1][0] = t1[0];
10788         decal->texcoord2f[1][1] = t1[1];
10789         decal->texcoord2f[2][0] = t2[0];
10790         decal->texcoord2f[2][1] = t2[1];
10791         TriangleNormal(v0, v1, v2, decal->plane);
10792         VectorNormalize(decal->plane);
10793         decal->plane[3] = DotProduct(v0, decal->plane);
10794 }
10795
10796 extern cvar_t cl_decals_bias;
10797 extern cvar_t cl_decals_models;
10798 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10799 // baseparms, parms, temps
10800 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)
10801 {
10802         int cornerindex;
10803         int index;
10804         float v[9][3];
10805         const float *vertex3f;
10806         const float *normal3f;
10807         int numpoints;
10808         float points[2][9][3];
10809         float temp[3];
10810         float tc[9][2];
10811         float f;
10812         float c[9][4];
10813         const int *e;
10814
10815         e = rsurface.modelelement3i + 3*triangleindex;
10816
10817         vertex3f = rsurface.modelvertex3f;
10818         normal3f = rsurface.modelnormal3f;
10819
10820         if (normal3f)
10821         {
10822                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10823                 {
10824                         index = 3*e[cornerindex];
10825                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10826                 }
10827         }
10828         else
10829         {
10830                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10831                 {
10832                         index = 3*e[cornerindex];
10833                         VectorCopy(vertex3f + index, v[cornerindex]);
10834                 }
10835         }
10836
10837         // cull backfaces
10838         //TriangleNormal(v[0], v[1], v[2], normal);
10839         //if (DotProduct(normal, localnormal) < 0.0f)
10840         //      continue;
10841         // clip by each of the box planes formed from the projection matrix
10842         // if anything survives, we emit the decal
10843         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]);
10844         if (numpoints < 3)
10845                 return;
10846         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]);
10847         if (numpoints < 3)
10848                 return;
10849         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]);
10850         if (numpoints < 3)
10851                 return;
10852         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]);
10853         if (numpoints < 3)
10854                 return;
10855         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]);
10856         if (numpoints < 3)
10857                 return;
10858         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]);
10859         if (numpoints < 3)
10860                 return;
10861         // some part of the triangle survived, so we have to accept it...
10862         if (dynamic)
10863         {
10864                 // dynamic always uses the original triangle
10865                 numpoints = 3;
10866                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10867                 {
10868                         index = 3*e[cornerindex];
10869                         VectorCopy(vertex3f + index, v[cornerindex]);
10870                 }
10871         }
10872         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10873         {
10874                 // convert vertex positions to texcoords
10875                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10876                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10877                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10878                 // calculate distance fade from the projection origin
10879                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10880                 f = bound(0.0f, f, 1.0f);
10881                 c[cornerindex][0] = r * f;
10882                 c[cornerindex][1] = g * f;
10883                 c[cornerindex][2] = b * f;
10884                 c[cornerindex][3] = 1.0f;
10885                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10886         }
10887         if (dynamic)
10888                 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);
10889         else
10890                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10891                         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);
10892 }
10893 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)
10894 {
10895         matrix4x4_t projection;
10896         decalsystem_t *decalsystem;
10897         qboolean dynamic;
10898         dp_model_t *model;
10899         const msurface_t *surface;
10900         const msurface_t *surfaces;
10901         const int *surfacelist;
10902         const texture_t *texture;
10903         int numtriangles;
10904         int numsurfacelist;
10905         int surfacelistindex;
10906         int surfaceindex;
10907         int triangleindex;
10908         float localorigin[3];
10909         float localnormal[3];
10910         float localmins[3];
10911         float localmaxs[3];
10912         float localsize;
10913         //float normal[3];
10914         float planes[6][4];
10915         float angles[3];
10916         bih_t *bih;
10917         int bih_triangles_count;
10918         int bih_triangles[256];
10919         int bih_surfaces[256];
10920
10921         decalsystem = &ent->decalsystem;
10922         model = ent->model;
10923         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10924         {
10925                 R_DecalSystem_Reset(&ent->decalsystem);
10926                 return;
10927         }
10928
10929         if (!model->brush.data_leafs && !cl_decals_models.integer)
10930         {
10931                 if (decalsystem->model)
10932                         R_DecalSystem_Reset(decalsystem);
10933                 return;
10934         }
10935
10936         if (decalsystem->model != model)
10937                 R_DecalSystem_Reset(decalsystem);
10938         decalsystem->model = model;
10939
10940         RSurf_ActiveModelEntity(ent, true, false, false);
10941
10942         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10943         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10944         VectorNormalize(localnormal);
10945         localsize = worldsize*rsurface.inversematrixscale;
10946         localmins[0] = localorigin[0] - localsize;
10947         localmins[1] = localorigin[1] - localsize;
10948         localmins[2] = localorigin[2] - localsize;
10949         localmaxs[0] = localorigin[0] + localsize;
10950         localmaxs[1] = localorigin[1] + localsize;
10951         localmaxs[2] = localorigin[2] + localsize;
10952
10953         //VectorCopy(localnormal, planes[4]);
10954         //VectorVectors(planes[4], planes[2], planes[0]);
10955         AnglesFromVectors(angles, localnormal, NULL, false);
10956         AngleVectors(angles, planes[0], planes[2], planes[4]);
10957         VectorNegate(planes[0], planes[1]);
10958         VectorNegate(planes[2], planes[3]);
10959         VectorNegate(planes[4], planes[5]);
10960         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10961         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10962         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10963         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10964         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10965         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10966
10967 #if 1
10968 // works
10969 {
10970         matrix4x4_t forwardprojection;
10971         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10972         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10973 }
10974 #else
10975 // broken
10976 {
10977         float projectionvector[4][3];
10978         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10979         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10980         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10981         projectionvector[0][0] = planes[0][0] * ilocalsize;
10982         projectionvector[0][1] = planes[1][0] * ilocalsize;
10983         projectionvector[0][2] = planes[2][0] * ilocalsize;
10984         projectionvector[1][0] = planes[0][1] * ilocalsize;
10985         projectionvector[1][1] = planes[1][1] * ilocalsize;
10986         projectionvector[1][2] = planes[2][1] * ilocalsize;
10987         projectionvector[2][0] = planes[0][2] * ilocalsize;
10988         projectionvector[2][1] = planes[1][2] * ilocalsize;
10989         projectionvector[2][2] = planes[2][2] * ilocalsize;
10990         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10991         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10992         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10993         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10994 }
10995 #endif
10996
10997         dynamic = model->surfmesh.isanimated;
10998         numsurfacelist = model->nummodelsurfaces;
10999         surfacelist = model->sortedmodelsurfaces;
11000         surfaces = model->data_surfaces;
11001
11002         bih = NULL;
11003         bih_triangles_count = -1;
11004         if(!dynamic)
11005         {
11006                 if(model->render_bih.numleafs)
11007                         bih = &model->render_bih;
11008                 else if(model->collision_bih.numleafs)
11009                         bih = &model->collision_bih;
11010         }
11011         if(bih)
11012                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11013         if(bih_triangles_count == 0)
11014                 return;
11015         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11016                 return;
11017         if(bih_triangles_count > 0)
11018         {
11019                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11020                 {
11021                         surfaceindex = bih_surfaces[triangleindex];
11022                         surface = surfaces + surfaceindex;
11023                         texture = surface->texture;
11024                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11025                                 continue;
11026                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11027                                 continue;
11028                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11029                 }
11030         }
11031         else
11032         {
11033                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11034                 {
11035                         surfaceindex = surfacelist[surfacelistindex];
11036                         surface = surfaces + surfaceindex;
11037                         // check cull box first because it rejects more than any other check
11038                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11039                                 continue;
11040                         // skip transparent surfaces
11041                         texture = surface->texture;
11042                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11043                                 continue;
11044                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11045                                 continue;
11046                         numtriangles = surface->num_triangles;
11047                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11048                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11049                 }
11050         }
11051 }
11052
11053 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11054 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)
11055 {
11056         int renderentityindex;
11057         float worldmins[3];
11058         float worldmaxs[3];
11059         entity_render_t *ent;
11060
11061         if (!cl_decals_newsystem.integer)
11062                 return;
11063
11064         worldmins[0] = worldorigin[0] - worldsize;
11065         worldmins[1] = worldorigin[1] - worldsize;
11066         worldmins[2] = worldorigin[2] - worldsize;
11067         worldmaxs[0] = worldorigin[0] + worldsize;
11068         worldmaxs[1] = worldorigin[1] + worldsize;
11069         worldmaxs[2] = worldorigin[2] + worldsize;
11070
11071         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11072
11073         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11074         {
11075                 ent = r_refdef.scene.entities[renderentityindex];
11076                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11077                         continue;
11078
11079                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11080         }
11081 }
11082
11083 typedef struct r_decalsystem_splatqueue_s
11084 {
11085         vec3_t worldorigin;
11086         vec3_t worldnormal;
11087         float color[4];
11088         float tcrange[4];
11089         float worldsize;
11090         int decalsequence;
11091 }
11092 r_decalsystem_splatqueue_t;
11093
11094 int r_decalsystem_numqueued = 0;
11095 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11096
11097 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)
11098 {
11099         r_decalsystem_splatqueue_t *queue;
11100
11101         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11102                 return;
11103
11104         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11105         VectorCopy(worldorigin, queue->worldorigin);
11106         VectorCopy(worldnormal, queue->worldnormal);
11107         Vector4Set(queue->color, r, g, b, a);
11108         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11109         queue->worldsize = worldsize;
11110         queue->decalsequence = cl.decalsequence++;
11111 }
11112
11113 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11114 {
11115         int i;
11116         r_decalsystem_splatqueue_t *queue;
11117
11118         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11119                 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);
11120         r_decalsystem_numqueued = 0;
11121 }
11122
11123 extern cvar_t cl_decals_max;
11124 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11125 {
11126         int i;
11127         decalsystem_t *decalsystem = &ent->decalsystem;
11128         int numdecals;
11129         int killsequence;
11130         tridecal_t *decal;
11131         float frametime;
11132         float lifetime;
11133
11134         if (!decalsystem->numdecals)
11135                 return;
11136
11137         if (r_showsurfaces.integer)
11138                 return;
11139
11140         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11141         {
11142                 R_DecalSystem_Reset(decalsystem);
11143                 return;
11144         }
11145
11146         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11147         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11148
11149         if (decalsystem->lastupdatetime)
11150                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11151         else
11152                 frametime = 0;
11153         decalsystem->lastupdatetime = r_refdef.scene.time;
11154         decal = decalsystem->decals;
11155         numdecals = decalsystem->numdecals;
11156
11157         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11158         {
11159                 if (decal->color4f[0][3])
11160                 {
11161                         decal->lived += frametime;
11162                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11163                         {
11164                                 memset(decal, 0, sizeof(*decal));
11165                                 if (decalsystem->freedecal > i)
11166                                         decalsystem->freedecal = i;
11167                         }
11168                 }
11169         }
11170         decal = decalsystem->decals;
11171         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11172                 numdecals--;
11173
11174         // collapse the array by shuffling the tail decals into the gaps
11175         for (;;)
11176         {
11177                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11178                         decalsystem->freedecal++;
11179                 if (decalsystem->freedecal == numdecals)
11180                         break;
11181                 decal[decalsystem->freedecal] = decal[--numdecals];
11182         }
11183
11184         decalsystem->numdecals = numdecals;
11185
11186         if (numdecals <= 0)
11187         {
11188                 // if there are no decals left, reset decalsystem
11189                 R_DecalSystem_Reset(decalsystem);
11190         }
11191 }
11192
11193 extern skinframe_t *decalskinframe;
11194 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11195 {
11196         int i;
11197         decalsystem_t *decalsystem = &ent->decalsystem;
11198         int numdecals;
11199         tridecal_t *decal;
11200         float faderate;
11201         float alpha;
11202         float *v3f;
11203         float *c4f;
11204         float *t2f;
11205         const int *e;
11206         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11207         int numtris = 0;
11208
11209         numdecals = decalsystem->numdecals;
11210         if (!numdecals)
11211                 return;
11212
11213         if (r_showsurfaces.integer)
11214                 return;
11215
11216         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11217         {
11218                 R_DecalSystem_Reset(decalsystem);
11219                 return;
11220         }
11221
11222         // if the model is static it doesn't matter what value we give for
11223         // wantnormals and wanttangents, so this logic uses only rules applicable
11224         // to a model, knowing that they are meaningless otherwise
11225         if (ent == r_refdef.scene.worldentity)
11226                 RSurf_ActiveWorldEntity();
11227         else
11228                 RSurf_ActiveModelEntity(ent, false, false, false);
11229
11230         decalsystem->lastupdatetime = r_refdef.scene.time;
11231         decal = decalsystem->decals;
11232
11233         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11234
11235         // update vertex positions for animated models
11236         v3f = decalsystem->vertex3f;
11237         c4f = decalsystem->color4f;
11238         t2f = decalsystem->texcoord2f;
11239         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11240         {
11241                 if (!decal->color4f[0][3])
11242                         continue;
11243
11244                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11245                         continue;
11246
11247                 // skip backfaces
11248                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11249                         continue;
11250
11251                 // update color values for fading decals
11252                 if (decal->lived >= cl_decals_time.value)
11253                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11254                 else
11255                         alpha = 1.0f;
11256
11257                 c4f[ 0] = decal->color4f[0][0] * alpha;
11258                 c4f[ 1] = decal->color4f[0][1] * alpha;
11259                 c4f[ 2] = decal->color4f[0][2] * alpha;
11260                 c4f[ 3] = 1;
11261                 c4f[ 4] = decal->color4f[1][0] * alpha;
11262                 c4f[ 5] = decal->color4f[1][1] * alpha;
11263                 c4f[ 6] = decal->color4f[1][2] * alpha;
11264                 c4f[ 7] = 1;
11265                 c4f[ 8] = decal->color4f[2][0] * alpha;
11266                 c4f[ 9] = decal->color4f[2][1] * alpha;
11267                 c4f[10] = decal->color4f[2][2] * alpha;
11268                 c4f[11] = 1;
11269
11270                 t2f[0] = decal->texcoord2f[0][0];
11271                 t2f[1] = decal->texcoord2f[0][1];
11272                 t2f[2] = decal->texcoord2f[1][0];
11273                 t2f[3] = decal->texcoord2f[1][1];
11274                 t2f[4] = decal->texcoord2f[2][0];
11275                 t2f[5] = decal->texcoord2f[2][1];
11276
11277                 // update vertex positions for animated models
11278                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11279                 {
11280                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11281                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11282                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11283                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11284                 }
11285                 else
11286                 {
11287                         VectorCopy(decal->vertex3f[0], v3f);
11288                         VectorCopy(decal->vertex3f[1], v3f + 3);
11289                         VectorCopy(decal->vertex3f[2], v3f + 6);
11290                 }
11291
11292                 if (r_refdef.fogenabled)
11293                 {
11294                         alpha = RSurf_FogVertex(v3f);
11295                         VectorScale(c4f, alpha, c4f);
11296                         alpha = RSurf_FogVertex(v3f + 3);
11297                         VectorScale(c4f + 4, alpha, c4f + 4);
11298                         alpha = RSurf_FogVertex(v3f + 6);
11299                         VectorScale(c4f + 8, alpha, c4f + 8);
11300                 }
11301
11302                 v3f += 9;
11303                 c4f += 12;
11304                 t2f += 6;
11305                 numtris++;
11306         }
11307
11308         if (numtris > 0)
11309         {
11310                 r_refdef.stats.drawndecals += numtris;
11311
11312                 // now render the decals all at once
11313                 // (this assumes they all use one particle font texture!)
11314                 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);
11315 //              R_Mesh_ResetTextureState();
11316                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11317                 GL_DepthMask(false);
11318                 GL_DepthRange(0, 1);
11319                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11320                 GL_DepthTest(true);
11321                 GL_CullFace(GL_NONE);
11322                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11323                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11324                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11325         }
11326 }
11327
11328 static void R_DrawModelDecals(void)
11329 {
11330         int i, numdecals;
11331
11332         // fade faster when there are too many decals
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_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11338         for (i = 0;i < r_refdef.scene.numentities;i++)
11339                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11340                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11341
11342         R_DecalSystem_ApplySplatEntitiesQueue();
11343
11344         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11345         for (i = 0;i < r_refdef.scene.numentities;i++)
11346                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11347
11348         r_refdef.stats.totaldecals += numdecals;
11349
11350         if (r_showsurfaces.integer)
11351                 return;
11352
11353         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11354
11355         for (i = 0;i < r_refdef.scene.numentities;i++)
11356         {
11357                 if (!r_refdef.viewcache.entityvisible[i])
11358                         continue;
11359                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11360                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11361         }
11362 }
11363
11364 extern cvar_t mod_collision_bih;
11365 void R_DrawDebugModel(void)
11366 {
11367         entity_render_t *ent = rsurface.entity;
11368         int i, j, k, l, flagsmask;
11369         const msurface_t *surface;
11370         dp_model_t *model = ent->model;
11371         vec3_t v;
11372
11373         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11374                 return;
11375
11376         if (r_showoverdraw.value > 0)
11377         {
11378                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11379                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11380                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11381                 GL_DepthTest(false);
11382                 GL_DepthMask(false);
11383                 GL_DepthRange(0, 1);
11384                 GL_BlendFunc(GL_ONE, GL_ONE);
11385                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11386                 {
11387                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11388                                 continue;
11389                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11390                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11391                         {
11392                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11393                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11394                                 if (!rsurface.texture->currentlayers->depthmask)
11395                                         GL_Color(c, 0, 0, 1.0f);
11396                                 else if (ent == r_refdef.scene.worldentity)
11397                                         GL_Color(c, c, c, 1.0f);
11398                                 else
11399                                         GL_Color(0, c, 0, 1.0f);
11400                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11401                                 RSurf_DrawBatch();
11402                         }
11403                 }
11404                 rsurface.texture = NULL;
11405         }
11406
11407         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11408
11409 //      R_Mesh_ResetTextureState();
11410         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11411         GL_DepthRange(0, 1);
11412         GL_DepthTest(!r_showdisabledepthtest.integer);
11413         GL_DepthMask(false);
11414         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11415
11416         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11417         {
11418                 int triangleindex;
11419                 int bihleafindex;
11420                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11421                 const q3mbrush_t *brush;
11422                 const bih_t *bih = &model->collision_bih;
11423                 const bih_leaf_t *bihleaf;
11424                 float vertex3f[3][3];
11425                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11426                 cullbox = false;
11427                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11428                 {
11429                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11430                                 continue;
11431                         switch (bihleaf->type)
11432                         {
11433                         case BIH_BRUSH:
11434                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11435                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11436                                 {
11437                                         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);
11438                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11439                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11440                                 }
11441                                 break;
11442                         case BIH_COLLISIONTRIANGLE:
11443                                 triangleindex = bihleaf->itemindex;
11444                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11445                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11446                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11447                                 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);
11448                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11449                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11450                                 break;
11451                         case BIH_RENDERTRIANGLE:
11452                                 triangleindex = bihleaf->itemindex;
11453                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11454                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11455                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11456                                 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);
11457                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11458                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11459                                 break;
11460                         }
11461                 }
11462         }
11463
11464         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11465
11466 #ifndef USE_GLES2
11467         if (r_showtris.integer && qglPolygonMode)
11468         {
11469                 if (r_showdisabledepthtest.integer)
11470                 {
11471                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11472                         GL_DepthMask(false);
11473                 }
11474                 else
11475                 {
11476                         GL_BlendFunc(GL_ONE, GL_ZERO);
11477                         GL_DepthMask(true);
11478                 }
11479                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11480                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11481                 {
11482                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11483                                 continue;
11484                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11485                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11486                         {
11487                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11488                                 if (!rsurface.texture->currentlayers->depthmask)
11489                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11490                                 else if (ent == r_refdef.scene.worldentity)
11491                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11492                                 else
11493                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11494                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11495                                 RSurf_DrawBatch();
11496                         }
11497                 }
11498                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11499                 rsurface.texture = NULL;
11500         }
11501
11502         if (r_shownormals.value != 0 && qglBegin)
11503         {
11504                 if (r_showdisabledepthtest.integer)
11505                 {
11506                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11507                         GL_DepthMask(false);
11508                 }
11509                 else
11510                 {
11511                         GL_BlendFunc(GL_ONE, GL_ZERO);
11512                         GL_DepthMask(true);
11513                 }
11514                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11515                 {
11516                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11517                                 continue;
11518                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11519                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11520                         {
11521                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11522                                 qglBegin(GL_LINES);
11523                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11524                                 {
11525                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11526                                         {
11527                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11528                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11529                                                 qglVertex3f(v[0], v[1], v[2]);
11530                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11531                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11532                                                 qglVertex3f(v[0], v[1], v[2]);
11533                                         }
11534                                 }
11535                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11536                                 {
11537                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11538                                         {
11539                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11540                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11541                                                 qglVertex3f(v[0], v[1], v[2]);
11542                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11543                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11544                                                 qglVertex3f(v[0], v[1], v[2]);
11545                                         }
11546                                 }
11547                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11548                                 {
11549                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11550                                         {
11551                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11552                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11553                                                 qglVertex3f(v[0], v[1], v[2]);
11554                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11555                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11556                                                 qglVertex3f(v[0], v[1], v[2]);
11557                                         }
11558                                 }
11559                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11560                                 {
11561                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11562                                         {
11563                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11564                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11565                                                 qglVertex3f(v[0], v[1], v[2]);
11566                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11567                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11568                                                 qglVertex3f(v[0], v[1], v[2]);
11569                                         }
11570                                 }
11571                                 qglEnd();
11572                                 CHECKGLERROR
11573                         }
11574                 }
11575                 rsurface.texture = NULL;
11576         }
11577 #endif
11578 }
11579
11580 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11581 int r_maxsurfacelist = 0;
11582 const msurface_t **r_surfacelist = NULL;
11583 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11584 {
11585         int i, j, endj, flagsmask;
11586         dp_model_t *model = r_refdef.scene.worldmodel;
11587         msurface_t *surfaces;
11588         unsigned char *update;
11589         int numsurfacelist = 0;
11590         if (model == NULL)
11591                 return;
11592
11593         if (r_maxsurfacelist < model->num_surfaces)
11594         {
11595                 r_maxsurfacelist = model->num_surfaces;
11596                 if (r_surfacelist)
11597                         Mem_Free((msurface_t**)r_surfacelist);
11598                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11599         }
11600
11601         RSurf_ActiveWorldEntity();
11602
11603         surfaces = model->data_surfaces;
11604         update = model->brushq1.lightmapupdateflags;
11605
11606         // update light styles on this submodel
11607         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11608         {
11609                 model_brush_lightstyleinfo_t *style;
11610                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11611                 {
11612                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11613                         {
11614                                 int *list = style->surfacelist;
11615                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11616                                 for (j = 0;j < style->numsurfaces;j++)
11617                                         update[list[j]] = true;
11618                         }
11619                 }
11620         }
11621
11622         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11623
11624         if (debug)
11625         {
11626                 R_DrawDebugModel();
11627                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11628                 return;
11629         }
11630
11631         rsurface.lightmaptexture = NULL;
11632         rsurface.deluxemaptexture = NULL;
11633         rsurface.uselightmaptexture = false;
11634         rsurface.texture = NULL;
11635         rsurface.rtlight = NULL;
11636         numsurfacelist = 0;
11637         // add visible surfaces to draw list
11638         for (i = 0;i < model->nummodelsurfaces;i++)
11639         {
11640                 j = model->sortedmodelsurfaces[i];
11641                 if (r_refdef.viewcache.world_surfacevisible[j])
11642                         r_surfacelist[numsurfacelist++] = surfaces + j;
11643         }
11644         // update lightmaps if needed
11645         if (model->brushq1.firstrender)
11646         {
11647                 model->brushq1.firstrender = false;
11648                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11649                         if (update[j])
11650                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11651         }
11652         else if (update)
11653         {
11654                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11655                         if (r_refdef.viewcache.world_surfacevisible[j])
11656                                 if (update[j])
11657                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11658         }
11659         // don't do anything if there were no surfaces
11660         if (!numsurfacelist)
11661         {
11662                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11663                 return;
11664         }
11665         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11666
11667         // add to stats if desired
11668         if (r_speeds.integer && !skysurfaces && !depthonly)
11669         {
11670                 r_refdef.stats.world_surfaces += numsurfacelist;
11671                 for (j = 0;j < numsurfacelist;j++)
11672                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11673         }
11674
11675         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11676 }
11677
11678 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11679 {
11680         int i, j, endj, flagsmask;
11681         dp_model_t *model = ent->model;
11682         msurface_t *surfaces;
11683         unsigned char *update;
11684         int numsurfacelist = 0;
11685         if (model == NULL)
11686                 return;
11687
11688         if (r_maxsurfacelist < model->num_surfaces)
11689         {
11690                 r_maxsurfacelist = model->num_surfaces;
11691                 if (r_surfacelist)
11692                         Mem_Free((msurface_t **)r_surfacelist);
11693                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11694         }
11695
11696         // if the model is static it doesn't matter what value we give for
11697         // wantnormals and wanttangents, so this logic uses only rules applicable
11698         // to a model, knowing that they are meaningless otherwise
11699         if (ent == r_refdef.scene.worldentity)
11700                 RSurf_ActiveWorldEntity();
11701         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11702                 RSurf_ActiveModelEntity(ent, false, false, false);
11703         else if (prepass)
11704                 RSurf_ActiveModelEntity(ent, true, true, true);
11705         else if (depthonly)
11706         {
11707                 switch (vid.renderpath)
11708                 {
11709                 case RENDERPATH_GL20:
11710                 case RENDERPATH_D3D9:
11711                 case RENDERPATH_D3D10:
11712                 case RENDERPATH_D3D11:
11713                 case RENDERPATH_SOFT:
11714                 case RENDERPATH_GLES2:
11715                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11716                         break;
11717                 case RENDERPATH_GL11:
11718                 case RENDERPATH_GL13:
11719                 case RENDERPATH_GLES1:
11720                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11721                         break;
11722                 }
11723         }
11724         else
11725         {
11726                 switch (vid.renderpath)
11727                 {
11728                 case RENDERPATH_GL20:
11729                 case RENDERPATH_D3D9:
11730                 case RENDERPATH_D3D10:
11731                 case RENDERPATH_D3D11:
11732                 case RENDERPATH_SOFT:
11733                 case RENDERPATH_GLES2:
11734                         RSurf_ActiveModelEntity(ent, true, true, false);
11735                         break;
11736                 case RENDERPATH_GL11:
11737                 case RENDERPATH_GL13:
11738                 case RENDERPATH_GLES1:
11739                         RSurf_ActiveModelEntity(ent, true, false, false);
11740                         break;
11741                 }
11742         }
11743
11744         surfaces = model->data_surfaces;
11745         update = model->brushq1.lightmapupdateflags;
11746
11747         // update light styles
11748         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11749         {
11750                 model_brush_lightstyleinfo_t *style;
11751                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11752                 {
11753                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11754                         {
11755                                 int *list = style->surfacelist;
11756                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11757                                 for (j = 0;j < style->numsurfaces;j++)
11758                                         update[list[j]] = true;
11759                         }
11760                 }
11761         }
11762
11763         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11764
11765         if (debug)
11766         {
11767                 R_DrawDebugModel();
11768                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11769                 return;
11770         }
11771
11772         rsurface.lightmaptexture = NULL;
11773         rsurface.deluxemaptexture = NULL;
11774         rsurface.uselightmaptexture = false;
11775         rsurface.texture = NULL;
11776         rsurface.rtlight = NULL;
11777         numsurfacelist = 0;
11778         // add visible surfaces to draw list
11779         for (i = 0;i < model->nummodelsurfaces;i++)
11780                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11781         // don't do anything if there were no surfaces
11782         if (!numsurfacelist)
11783         {
11784                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11785                 return;
11786         }
11787         // update lightmaps if needed
11788         if (update)
11789         {
11790                 int updated = 0;
11791                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11792                 {
11793                         if (update[j])
11794                         {
11795                                 updated++;
11796                                 R_BuildLightMap(ent, surfaces + j);
11797                         }
11798                 }
11799         }
11800         if (update)
11801                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11802                         if (update[j])
11803                                 R_BuildLightMap(ent, surfaces + j);
11804         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11805
11806         // add to stats if desired
11807         if (r_speeds.integer && !skysurfaces && !depthonly)
11808         {
11809                 r_refdef.stats.entities_surfaces += numsurfacelist;
11810                 for (j = 0;j < numsurfacelist;j++)
11811                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11812         }
11813
11814         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11815 }
11816
11817 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11818 {
11819         static texture_t texture;
11820         static msurface_t surface;
11821         const msurface_t *surfacelist = &surface;
11822
11823         // fake enough texture and surface state to render this geometry
11824
11825         texture.update_lastrenderframe = -1; // regenerate this texture
11826         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11827         texture.currentskinframe = skinframe;
11828         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11829         texture.offsetmapping = OFFSETMAPPING_OFF;
11830         texture.offsetscale = 1;
11831         texture.specularscalemod = 1;
11832         texture.specularpowermod = 1;
11833
11834         surface.texture = &texture;
11835         surface.num_triangles = numtriangles;
11836         surface.num_firsttriangle = firsttriangle;
11837         surface.num_vertices = numvertices;
11838         surface.num_firstvertex = firstvertex;
11839
11840         // now render it
11841         rsurface.texture = R_GetCurrentTexture(surface.texture);
11842         rsurface.lightmaptexture = NULL;
11843         rsurface.deluxemaptexture = NULL;
11844         rsurface.uselightmaptexture = false;
11845         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11846 }
11847
11848 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)
11849 {
11850         static msurface_t surface;
11851         const msurface_t *surfacelist = &surface;
11852
11853         // fake enough texture and surface state to render this geometry
11854         surface.texture = texture;
11855         surface.num_triangles = numtriangles;
11856         surface.num_firsttriangle = firsttriangle;
11857         surface.num_vertices = numvertices;
11858         surface.num_firstvertex = firstvertex;
11859
11860         // now render it
11861         rsurface.texture = R_GetCurrentTexture(surface.texture);
11862         rsurface.lightmaptexture = NULL;
11863         rsurface.deluxemaptexture = NULL;
11864         rsurface.uselightmaptexture = false;
11865         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11866 }