]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
8b04c0fe15887d403aad667debc652972bf874da
[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
196 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
197 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
198 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
199 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
200 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
201
202 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
203 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
204 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
205 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
206 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
209 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
210 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
212
213 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"};
214
215 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"};
216
217 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
218
219 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
220
221 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
222 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"};
223
224 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."};
225
226 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)"};
227
228 extern cvar_t v_glslgamma;
229 extern cvar_t v_glslgamma_2d;
230
231 extern qboolean v_flipped_state;
232
233 r_framebufferstate_t r_fb;
234
235 /// shadow volume bsp struct with automatically growing nodes buffer
236 svbsp_t r_svbsp;
237
238 rtexture_t *r_texture_blanknormalmap;
239 rtexture_t *r_texture_white;
240 rtexture_t *r_texture_grey128;
241 rtexture_t *r_texture_black;
242 rtexture_t *r_texture_notexture;
243 rtexture_t *r_texture_whitecube;
244 rtexture_t *r_texture_normalizationcube;
245 rtexture_t *r_texture_fogattenuation;
246 rtexture_t *r_texture_fogheighttexture;
247 rtexture_t *r_texture_gammaramps;
248 unsigned int r_texture_gammaramps_serial;
249 //rtexture_t *r_texture_fogintensity;
250 rtexture_t *r_texture_reflectcube;
251
252 // TODO: hash lookups?
253 typedef struct cubemapinfo_s
254 {
255         char basename[64];
256         rtexture_t *texture;
257 }
258 cubemapinfo_t;
259
260 int r_texture_numcubemaps;
261 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
262
263 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
264 unsigned int r_numqueries;
265 unsigned int r_maxqueries;
266
267 typedef struct r_qwskincache_s
268 {
269         char name[MAX_QPATH];
270         skinframe_t *skinframe;
271 }
272 r_qwskincache_t;
273
274 static r_qwskincache_t *r_qwskincache;
275 static int r_qwskincache_size;
276
277 /// vertex coordinates for a quad that covers the screen exactly
278 extern const float r_screenvertex3f[12];
279 extern const float r_d3dscreenvertex3f[12];
280 const float r_screenvertex3f[12] =
281 {
282         0, 0, 0,
283         1, 0, 0,
284         1, 1, 0,
285         0, 1, 0
286 };
287 const float r_d3dscreenvertex3f[12] =
288 {
289         0, 1, 0,
290         1, 1, 0,
291         1, 0, 0,
292         0, 0, 0
293 };
294
295 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
296 {
297         int i;
298         for (i = 0;i < verts;i++)
299         {
300                 out[0] = in[0] * r;
301                 out[1] = in[1] * g;
302                 out[2] = in[2] * b;
303                 out[3] = in[3];
304                 in += 4;
305                 out += 4;
306         }
307 }
308
309 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
310 {
311         int i;
312         for (i = 0;i < verts;i++)
313         {
314                 out[0] = r;
315                 out[1] = g;
316                 out[2] = b;
317                 out[3] = a;
318                 out += 4;
319         }
320 }
321
322 // FIXME: move this to client?
323 void FOG_clear(void)
324 {
325         if (gamemode == GAME_NEHAHRA)
326         {
327                 Cvar_Set("gl_fogenable", "0");
328                 Cvar_Set("gl_fogdensity", "0.2");
329                 Cvar_Set("gl_fogred", "0.3");
330                 Cvar_Set("gl_foggreen", "0.3");
331                 Cvar_Set("gl_fogblue", "0.3");
332         }
333         r_refdef.fog_density = 0;
334         r_refdef.fog_red = 0;
335         r_refdef.fog_green = 0;
336         r_refdef.fog_blue = 0;
337         r_refdef.fog_alpha = 1;
338         r_refdef.fog_start = 0;
339         r_refdef.fog_end = 16384;
340         r_refdef.fog_height = 1<<30;
341         r_refdef.fog_fadedepth = 128;
342         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
343 }
344
345 static void R_BuildBlankTextures(void)
346 {
347         unsigned char data[4];
348         data[2] = 128; // normal X
349         data[1] = 128; // normal Y
350         data[0] = 255; // normal Z
351         data[3] = 255; // height
352         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 255;
354         data[1] = 255;
355         data[2] = 255;
356         data[3] = 255;
357         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 128;
359         data[1] = 128;
360         data[2] = 128;
361         data[3] = 255;
362         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 0;
364         data[1] = 0;
365         data[2] = 0;
366         data[3] = 255;
367         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368 }
369
370 static void R_BuildNoTexture(void)
371 {
372         int x, y;
373         unsigned char pix[16][16][4];
374         // this makes a light grey/dark grey checkerboard texture
375         for (y = 0;y < 16;y++)
376         {
377                 for (x = 0;x < 16;x++)
378                 {
379                         if ((y < 8) ^ (x < 8))
380                         {
381                                 pix[y][x][0] = 128;
382                                 pix[y][x][1] = 128;
383                                 pix[y][x][2] = 128;
384                                 pix[y][x][3] = 255;
385                         }
386                         else
387                         {
388                                 pix[y][x][0] = 64;
389                                 pix[y][x][1] = 64;
390                                 pix[y][x][2] = 64;
391                                 pix[y][x][3] = 255;
392                         }
393                 }
394         }
395         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildWhiteCube(void)
399 {
400         unsigned char data[6*1*1*4];
401         memset(data, 255, sizeof(data));
402         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNormalizationCube(void)
406 {
407         int x, y, side;
408         vec3_t v;
409         vec_t s, t, intensity;
410 #define NORMSIZE 64
411         unsigned char *data;
412         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
413         for (side = 0;side < 6;side++)
414         {
415                 for (y = 0;y < NORMSIZE;y++)
416                 {
417                         for (x = 0;x < NORMSIZE;x++)
418                         {
419                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
421                                 switch(side)
422                                 {
423                                 default:
424                                 case 0:
425                                         v[0] = 1;
426                                         v[1] = -t;
427                                         v[2] = -s;
428                                         break;
429                                 case 1:
430                                         v[0] = -1;
431                                         v[1] = -t;
432                                         v[2] = s;
433                                         break;
434                                 case 2:
435                                         v[0] = s;
436                                         v[1] = 1;
437                                         v[2] = t;
438                                         break;
439                                 case 3:
440                                         v[0] = s;
441                                         v[1] = -1;
442                                         v[2] = -t;
443                                         break;
444                                 case 4:
445                                         v[0] = s;
446                                         v[1] = -t;
447                                         v[2] = 1;
448                                         break;
449                                 case 5:
450                                         v[0] = -s;
451                                         v[1] = -t;
452                                         v[2] = -1;
453                                         break;
454                                 }
455                                 intensity = 127.0f / sqrt(DotProduct(v, v));
456                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
457                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
458                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
459                                 data[((side*64+y)*64+x)*4+3] = 255;
460                         }
461                 }
462         }
463         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
464         Mem_Free(data);
465 }
466
467 static void R_BuildFogTexture(void)
468 {
469         int x, b;
470 #define FOGWIDTH 256
471         unsigned char data1[FOGWIDTH][4];
472         //unsigned char data2[FOGWIDTH][4];
473         double d, r, alpha;
474
475         r_refdef.fogmasktable_start = r_refdef.fog_start;
476         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
477         r_refdef.fogmasktable_range = r_refdef.fogrange;
478         r_refdef.fogmasktable_density = r_refdef.fog_density;
479
480         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
481         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
482         {
483                 d = (x * r - r_refdef.fogmasktable_start);
484                 if(developer_extra.integer)
485                         Con_DPrintf("%f ", d);
486                 d = max(0, d);
487                 if (r_fog_exp2.integer)
488                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
489                 else
490                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
491                 if(developer_extra.integer)
492                         Con_DPrintf(" : %f ", alpha);
493                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
494                 if(developer_extra.integer)
495                         Con_DPrintf(" = %f\n", alpha);
496                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
497         }
498
499         for (x = 0;x < FOGWIDTH;x++)
500         {
501                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502                 data1[x][0] = b;
503                 data1[x][1] = b;
504                 data1[x][2] = b;
505                 data1[x][3] = 255;
506                 //data2[x][0] = 255 - b;
507                 //data2[x][1] = 255 - b;
508                 //data2[x][2] = 255 - b;
509                 //data2[x][3] = 255;
510         }
511         if (r_texture_fogattenuation)
512         {
513                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
515         }
516         else
517         {
518                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
519                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
520         }
521 }
522
523 static void R_BuildFogHeightTexture(void)
524 {
525         unsigned char *inpixels;
526         int size;
527         int x;
528         int y;
529         int j;
530         float c[4];
531         float f;
532         inpixels = NULL;
533         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
534         if (r_refdef.fogheighttexturename[0])
535                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
536         if (!inpixels)
537         {
538                 r_refdef.fog_height_tablesize = 0;
539                 if (r_texture_fogheighttexture)
540                         R_FreeTexture(r_texture_fogheighttexture);
541                 r_texture_fogheighttexture = NULL;
542                 if (r_refdef.fog_height_table2d)
543                         Mem_Free(r_refdef.fog_height_table2d);
544                 r_refdef.fog_height_table2d = NULL;
545                 if (r_refdef.fog_height_table1d)
546                         Mem_Free(r_refdef.fog_height_table1d);
547                 r_refdef.fog_height_table1d = NULL;
548                 return;
549         }
550         size = image_width;
551         r_refdef.fog_height_tablesize = size;
552         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
553         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
554         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
555         Mem_Free(inpixels);
556         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
557         // average fog color table accounting for every fog layer between a point
558         // and the camera.  (Note: attenuation is handled separately!)
559         for (y = 0;y < size;y++)
560         {
561                 for (x = 0;x < size;x++)
562                 {
563                         Vector4Clear(c);
564                         f = 0;
565                         if (x < y)
566                         {
567                                 for (j = x;j <= y;j++)
568                                 {
569                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570                                         f++;
571                                 }
572                         }
573                         else
574                         {
575                                 for (j = x;j >= y;j--)
576                                 {
577                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578                                         f++;
579                                 }
580                         }
581                         f = 1.0f / f;
582                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
586                 }
587         }
588         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
589 }
590
591 //=======================================================================================================================================================
592
593 static const char *builtinshaderstring =
594 #include "shader_glsl.h"
595 ;
596
597 const char *builtinhlslshaderstring =
598 #include "shader_hlsl.h"
599 ;
600
601 char *glslshaderstring = NULL;
602 char *hlslshaderstring = NULL;
603
604 //=======================================================================================================================================================
605
606 typedef struct shaderpermutationinfo_s
607 {
608         const char *pretext;
609         const char *name;
610 }
611 shaderpermutationinfo_t;
612
613 typedef struct shadermodeinfo_s
614 {
615         const char *vertexfilename;
616         const char *geometryfilename;
617         const char *fragmentfilename;
618         const char *pretext;
619         const char *name;
620 }
621 shadermodeinfo_t;
622
623 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
624 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
625 {
626         {"#define USEDIFFUSE\n", " diffuse"},
627         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
628         {"#define USEVIEWTINT\n", " viewtint"},
629         {"#define USECOLORMAPPING\n", " colormapping"},
630         {"#define USESATURATION\n", " saturation"},
631         {"#define USEFOGINSIDE\n", " foginside"},
632         {"#define USEFOGOUTSIDE\n", " fogoutside"},
633         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
634         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
635         {"#define USEGAMMARAMPS\n", " gammaramps"},
636         {"#define USECUBEFILTER\n", " cubefilter"},
637         {"#define USEGLOW\n", " glow"},
638         {"#define USEBLOOM\n", " bloom"},
639         {"#define USESPECULAR\n", " specular"},
640         {"#define USEPOSTPROCESSING\n", " postprocessing"},
641         {"#define USEREFLECTION\n", " reflection"},
642         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
643         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
644         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
645         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
646         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
647         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
656         {"#define USETRIPPY\n", " trippy"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 };
681
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         unsigned int permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenDepth;
741         int tex_Texture_ScreenNormalMap;
742         int tex_Texture_ScreenDiffuse;
743         int tex_Texture_ScreenSpecular;
744         int tex_Texture_ReflectMask;
745         int tex_Texture_ReflectCube;
746         int tex_Texture_BounceGrid;
747         /// locations of detected uniforms in program object, or -1 if not found
748         int loc_Texture_First;
749         int loc_Texture_Second;
750         int loc_Texture_GammaRamps;
751         int loc_Texture_Normal;
752         int loc_Texture_Color;
753         int loc_Texture_Gloss;
754         int loc_Texture_Glow;
755         int loc_Texture_SecondaryNormal;
756         int loc_Texture_SecondaryColor;
757         int loc_Texture_SecondaryGloss;
758         int loc_Texture_SecondaryGlow;
759         int loc_Texture_Pants;
760         int loc_Texture_Shirt;
761         int loc_Texture_FogHeightTexture;
762         int loc_Texture_FogMask;
763         int loc_Texture_Lightmap;
764         int loc_Texture_Deluxemap;
765         int loc_Texture_Attenuation;
766         int loc_Texture_Cube;
767         int loc_Texture_Refraction;
768         int loc_Texture_Reflection;
769         int loc_Texture_ShadowMap2D;
770         int loc_Texture_CubeProjection;
771         int loc_Texture_ScreenDepth;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853 };
854 #define SHADERSTATICPARMS_COUNT 8
855
856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
857 static int shaderstaticparms_count = 0;
858
859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
861 static qboolean R_CompileShader_CheckStaticParms(void)
862 {
863         static int r_compileshader_staticparms_save[1];
864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866
867         // detect all
868         if (r_glsl_saturation_redcompensate.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
870         if (r_glsl_vertextextureblend_usebothalphas.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
872         if (r_shadow_glossexact.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
874         if (r_glsl_postprocess.integer)
875         {
876                 if (r_glsl_postprocess_uservec1_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
878                 if (r_glsl_postprocess_uservec2_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
880                 if (r_glsl_postprocess_uservec3_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
882                 if (r_glsl_postprocess_uservec4_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884         }
885         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
887         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
888 }
889
890 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
891         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
893         else \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
895 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
896 {
897         shaderstaticparms_count = 0;
898
899         // emit all
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
908 }
909
910 /// information about each possible shader permutation
911 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
912 /// currently selected permutation
913 r_glsl_permutation_t *r_glsl_permutation;
914 /// storage for permutations linked in the hash table
915 memexpandablearray_t r_glsl_permutationarray;
916
917 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
918 {
919         //unsigned int hashdepth = 0;
920         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
921         r_glsl_permutation_t *p;
922         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
923         {
924                 if (p->mode == mode && p->permutation == permutation)
925                 {
926                         //if (hashdepth > 10)
927                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928                         return p;
929                 }
930                 //hashdepth++;
931         }
932         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
933         p->mode = mode;
934         p->permutation = permutation;
935         p->hashnext = r_glsl_permutationhash[mode][hashindex];
936         r_glsl_permutationhash[mode][hashindex] = p;
937         //if (hashdepth > 10)
938         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939         return p;
940 }
941
942 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
943 {
944         char *shaderstring;
945         if (!filename || !filename[0])
946                 return NULL;
947         if (!strcmp(filename, "glsl/default.glsl"))
948         {
949                 if (!glslshaderstring)
950                 {
951                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952                         if (glslshaderstring)
953                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
954                         else
955                                 glslshaderstring = (char *)builtinshaderstring;
956                 }
957                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
958                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
959                 return shaderstring;
960         }
961         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
962         if (shaderstring)
963         {
964                 if (printfromdisknotice)
965                         Con_DPrintf("from disk %s... ", filename);
966                 return shaderstring;
967         }
968         return shaderstring;
969 }
970
971 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
972 {
973         int i;
974         int sampler;
975         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
976         char *vertexstring, *geometrystring, *fragmentstring;
977         char permutationname[256];
978         int vertstrings_count = 0;
979         int geomstrings_count = 0;
980         int fragstrings_count = 0;
981         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
984
985         if (p->compiled)
986                 return;
987         p->compiled = true;
988         p->program = 0;
989
990         permutationname[0] = 0;
991         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
992         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
993         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
994
995         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
996
997         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
998         if(vid.support.gl20shaders130)
999         {
1000                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1001                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1002                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1003                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1004                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1005                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1006         }
1007
1008         // the first pretext is which type of shader to compile as
1009         // (later these will all be bound together as a program object)
1010         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1011         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1012         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1013
1014         // the second pretext is the mode (for example a light source)
1015         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1016         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1017         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1018         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1019
1020         // now add all the permutation pretexts
1021         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1022         {
1023                 if (permutation & (1<<i))
1024                 {
1025                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1029                 }
1030                 else
1031                 {
1032                         // keep line numbers correct
1033                         vertstrings_list[vertstrings_count++] = "\n";
1034                         geomstrings_list[geomstrings_count++] = "\n";
1035                         fragstrings_list[fragstrings_count++] = "\n";
1036                 }
1037         }
1038
1039         // add static parms
1040         R_CompileShader_AddStaticParms(mode, permutation);
1041         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         vertstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         geomstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         fragstrings_count += shaderstaticparms_count;
1047
1048         // now append the shader text itself
1049         vertstrings_list[vertstrings_count++] = vertexstring;
1050         geomstrings_list[geomstrings_count++] = geometrystring;
1051         fragstrings_list[fragstrings_count++] = fragmentstring;
1052
1053         // if any sources were NULL, clear the respective list
1054         if (!vertexstring)
1055                 vertstrings_count = 0;
1056         if (!geometrystring)
1057                 geomstrings_count = 0;
1058         if (!fragmentstring)
1059                 fragstrings_count = 0;
1060
1061         // compile the shader program
1062         if (vertstrings_count + geomstrings_count + fragstrings_count)
1063                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1064         if (p->program)
1065         {
1066                 CHECKGLERROR
1067                 qglUseProgram(p->program);CHECKGLERROR
1068                 // look up all the uniform variable names we care about, so we don't
1069                 // have to look them up every time we set them
1070
1071                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1072                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1073                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1074                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1075                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1076                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1077                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1078                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1079                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1080                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1081                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1082                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1083                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1084                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1085                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1086                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1087                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1088                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1089                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1090                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1091                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1092                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1093                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1094                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1095                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1096                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1097                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1098                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1099                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1100                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1101                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1102                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1103                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1104                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1105                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1106                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1107                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1108                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1109                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1110                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1111                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1112                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1113                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1114                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1115                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1116                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1117                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1118                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1119                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1120                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1121                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1122                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1123                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1124                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1125                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1126                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1127                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1128                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1129                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1130                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1131                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1132                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1133                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1134                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1135                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1136                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1137                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1138                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1139                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1140                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1141                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1142                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1143                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1144                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1145                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1146                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1147                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1148                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1149                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1150                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1151                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1152                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1153                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1154                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1155                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1156                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1157                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1158                 // initialize the samplers to refer to the texture units we use
1159                 p->tex_Texture_First = -1;
1160                 p->tex_Texture_Second = -1;
1161                 p->tex_Texture_GammaRamps = -1;
1162                 p->tex_Texture_Normal = -1;
1163                 p->tex_Texture_Color = -1;
1164                 p->tex_Texture_Gloss = -1;
1165                 p->tex_Texture_Glow = -1;
1166                 p->tex_Texture_SecondaryNormal = -1;
1167                 p->tex_Texture_SecondaryColor = -1;
1168                 p->tex_Texture_SecondaryGloss = -1;
1169                 p->tex_Texture_SecondaryGlow = -1;
1170                 p->tex_Texture_Pants = -1;
1171                 p->tex_Texture_Shirt = -1;
1172                 p->tex_Texture_FogHeightTexture = -1;
1173                 p->tex_Texture_FogMask = -1;
1174                 p->tex_Texture_Lightmap = -1;
1175                 p->tex_Texture_Deluxemap = -1;
1176                 p->tex_Texture_Attenuation = -1;
1177                 p->tex_Texture_Cube = -1;
1178                 p->tex_Texture_Refraction = -1;
1179                 p->tex_Texture_Reflection = -1;
1180                 p->tex_Texture_ShadowMap2D = -1;
1181                 p->tex_Texture_CubeProjection = -1;
1182                 p->tex_Texture_ScreenDepth = -1;
1183                 p->tex_Texture_ScreenNormalMap = -1;
1184                 p->tex_Texture_ScreenDiffuse = -1;
1185                 p->tex_Texture_ScreenSpecular = -1;
1186                 p->tex_Texture_ReflectMask = -1;
1187                 p->tex_Texture_ReflectCube = -1;
1188                 p->tex_Texture_BounceGrid = -1;
1189                 sampler = 0;
1190                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1191                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1192                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1193                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1194                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1195                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1196                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1200                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1201                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1202                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1203                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1204                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1205                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1206                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1207                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1208                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1209                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1210                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1211                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1212                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1216                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1218                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1219                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1220                 CHECKGLERROR
1221                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1222         }
1223         else
1224                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1225
1226         // free the strings
1227         if (vertexstring)
1228                 Mem_Free(vertexstring);
1229         if (geometrystring)
1230                 Mem_Free(geometrystring);
1231         if (fragmentstring)
1232                 Mem_Free(fragmentstring);
1233 }
1234
1235 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1236 {
1237         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1238         if (r_glsl_permutation != perm)
1239         {
1240                 r_glsl_permutation = perm;
1241                 if (!r_glsl_permutation->program)
1242                 {
1243                         if (!r_glsl_permutation->compiled)
1244                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1245                         if (!r_glsl_permutation->program)
1246                         {
1247                                 // remove features until we find a valid permutation
1248                                 int i;
1249                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250                                 {
1251                                         // reduce i more quickly whenever it would not remove any bits
1252                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1253                                         if (!(permutation & j))
1254                                                 continue;
1255                                         permutation -= j;
1256                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1257                                         if (!r_glsl_permutation->compiled)
1258                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                                         if (r_glsl_permutation->program)
1260                                                 break;
1261                                 }
1262                                 if (i >= SHADERPERMUTATION_COUNT)
1263                                 {
1264                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1265                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1266                                         qglUseProgram(0);CHECKGLERROR
1267                                         return; // no bit left to clear, entire mode is broken
1268                                 }
1269                         }
1270                 }
1271                 CHECKGLERROR
1272                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1273         }
1274         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1275         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1276         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 }
1278
1279 #ifdef SUPPORTD3D
1280
1281 #ifdef SUPPORTD3D
1282 #include <d3d9.h>
1283 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1284 extern D3DCAPS9 vid_d3d9caps;
1285 #endif
1286
1287 struct r_hlsl_permutation_s;
1288 typedef struct r_hlsl_permutation_s
1289 {
1290         /// hash lookup data
1291         struct r_hlsl_permutation_s *hashnext;
1292         unsigned int mode;
1293         unsigned int permutation;
1294
1295         /// indicates if we have tried compiling this permutation already
1296         qboolean compiled;
1297         /// NULL if compilation failed
1298         IDirect3DVertexShader9 *vertexshader;
1299         IDirect3DPixelShader9 *pixelshader;
1300 }
1301 r_hlsl_permutation_t;
1302
1303 typedef enum D3DVSREGISTER_e
1304 {
1305         D3DVSREGISTER_TexMatrix = 0, // float4x4
1306         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1307         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1308         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1309         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1310         D3DVSREGISTER_ModelToLight = 20, // float4x4
1311         D3DVSREGISTER_EyePosition = 24,
1312         D3DVSREGISTER_FogPlane = 25,
1313         D3DVSREGISTER_LightDir = 26,
1314         D3DVSREGISTER_LightPosition = 27,
1315 }
1316 D3DVSREGISTER_t;
1317
1318 typedef enum D3DPSREGISTER_e
1319 {
1320         D3DPSREGISTER_Alpha = 0,
1321         D3DPSREGISTER_BloomBlur_Parameters = 1,
1322         D3DPSREGISTER_ClientTime = 2,
1323         D3DPSREGISTER_Color_Ambient = 3,
1324         D3DPSREGISTER_Color_Diffuse = 4,
1325         D3DPSREGISTER_Color_Specular = 5,
1326         D3DPSREGISTER_Color_Glow = 6,
1327         D3DPSREGISTER_Color_Pants = 7,
1328         D3DPSREGISTER_Color_Shirt = 8,
1329         D3DPSREGISTER_DeferredColor_Ambient = 9,
1330         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1331         D3DPSREGISTER_DeferredColor_Specular = 11,
1332         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1333         D3DPSREGISTER_DeferredMod_Specular = 13,
1334         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1335         D3DPSREGISTER_EyePosition = 15, // unused
1336         D3DPSREGISTER_FogColor = 16,
1337         D3DPSREGISTER_FogHeightFade = 17,
1338         D3DPSREGISTER_FogPlane = 18,
1339         D3DPSREGISTER_FogPlaneViewDist = 19,
1340         D3DPSREGISTER_FogRangeRecip = 20,
1341         D3DPSREGISTER_LightColor = 21,
1342         D3DPSREGISTER_LightDir = 22, // unused
1343         D3DPSREGISTER_LightPosition = 23,
1344         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1345         D3DPSREGISTER_PixelSize = 25,
1346         D3DPSREGISTER_ReflectColor = 26,
1347         D3DPSREGISTER_ReflectFactor = 27,
1348         D3DPSREGISTER_ReflectOffset = 28,
1349         D3DPSREGISTER_RefractColor = 29,
1350         D3DPSREGISTER_Saturation = 30,
1351         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1352         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1353         D3DPSREGISTER_ScreenToDepth = 33,
1354         D3DPSREGISTER_ShadowMap_Parameters = 34,
1355         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1356         D3DPSREGISTER_SpecularPower = 36,
1357         D3DPSREGISTER_UserVec1 = 37,
1358         D3DPSREGISTER_UserVec2 = 38,
1359         D3DPSREGISTER_UserVec3 = 39,
1360         D3DPSREGISTER_UserVec4 = 40,
1361         D3DPSREGISTER_ViewTintColor = 41,
1362         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1363         D3DPSREGISTER_BloomColorSubtract = 43,
1364         D3DPSREGISTER_ViewToLight = 44, // float4x4
1365         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1366         D3DPSREGISTER_NormalmapScrollBlend = 52,
1367         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1368         D3DPSREGISTER_OffsetMapping_Bias = 54,
1369         // next at 54
1370 }
1371 D3DPSREGISTER_t;
1372
1373 /// information about each possible shader permutation
1374 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1375 /// currently selected permutation
1376 r_hlsl_permutation_t *r_hlsl_permutation;
1377 /// storage for permutations linked in the hash table
1378 memexpandablearray_t r_hlsl_permutationarray;
1379
1380 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1381 {
1382         //unsigned int hashdepth = 0;
1383         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1384         r_hlsl_permutation_t *p;
1385         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1386         {
1387                 if (p->mode == mode && p->permutation == permutation)
1388                 {
1389                         //if (hashdepth > 10)
1390                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1391                         return p;
1392                 }
1393                 //hashdepth++;
1394         }
1395         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1396         p->mode = mode;
1397         p->permutation = permutation;
1398         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1399         r_hlsl_permutationhash[mode][hashindex] = p;
1400         //if (hashdepth > 10)
1401         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1402         return p;
1403 }
1404
1405 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1406 {
1407         char *shaderstring;
1408         if (!filename || !filename[0])
1409                 return NULL;
1410         if (!strcmp(filename, "hlsl/default.hlsl"))
1411         {
1412                 if (!hlslshaderstring)
1413                 {
1414                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1415                         if (hlslshaderstring)
1416                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1417                         else
1418                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1419                 }
1420                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1421                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1422                 return shaderstring;
1423         }
1424         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425         if (shaderstring)
1426         {
1427                 if (printfromdisknotice)
1428                         Con_DPrintf("from disk %s... ", filename);
1429                 return shaderstring;
1430         }
1431         return shaderstring;
1432 }
1433
1434 #include <d3dx9.h>
1435 //#include <d3dx9shader.h>
1436 //#include <d3dx9mesh.h>
1437
1438 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1439 {
1440         DWORD *vsbin = NULL;
1441         DWORD *psbin = NULL;
1442         fs_offset_t vsbinsize;
1443         fs_offset_t psbinsize;
1444 //      IDirect3DVertexShader9 *vs = NULL;
1445 //      IDirect3DPixelShader9 *ps = NULL;
1446         ID3DXBuffer *vslog = NULL;
1447         ID3DXBuffer *vsbuffer = NULL;
1448         ID3DXConstantTable *vsconstanttable = NULL;
1449         ID3DXBuffer *pslog = NULL;
1450         ID3DXBuffer *psbuffer = NULL;
1451         ID3DXConstantTable *psconstanttable = NULL;
1452         int vsresult = 0;
1453         int psresult = 0;
1454         char temp[MAX_INPUTLINE];
1455         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1456         char vabuf[1024];
1457         qboolean debugshader = gl_paranoid.integer != 0;
1458         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1459         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460         if (!debugshader)
1461         {
1462                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1463                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1464         }
1465         if ((!vsbin && vertstring) || (!psbin && fragstring))
1466         {
1467                 const char* dllnames_d3dx9 [] =
1468                 {
1469                         "d3dx9_43.dll",
1470                         "d3dx9_42.dll",
1471                         "d3dx9_41.dll",
1472                         "d3dx9_40.dll",
1473                         "d3dx9_39.dll",
1474                         "d3dx9_38.dll",
1475                         "d3dx9_37.dll",
1476                         "d3dx9_36.dll",
1477                         "d3dx9_35.dll",
1478                         "d3dx9_34.dll",
1479                         "d3dx9_33.dll",
1480                         "d3dx9_32.dll",
1481                         "d3dx9_31.dll",
1482                         "d3dx9_30.dll",
1483                         "d3dx9_29.dll",
1484                         "d3dx9_28.dll",
1485                         "d3dx9_27.dll",
1486                         "d3dx9_26.dll",
1487                         "d3dx9_25.dll",
1488                         "d3dx9_24.dll",
1489                         NULL
1490                 };
1491                 dllhandle_t d3dx9_dll = NULL;
1492                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1493                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1494                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495                 dllfunction_t d3dx9_dllfuncs[] =
1496                 {
1497                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1498                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1499                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1500                         {NULL, NULL}
1501                 };
1502                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1503                 {
1504                         DWORD shaderflags = 0;
1505                         if (debugshader)
1506                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1507                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1508                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1509                         if (vertstring && vertstring[0])
1510                         {
1511                                 if (debugshader)
1512                                 {
1513 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1514 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1515                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1516                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1517                                 }
1518                                 else
1519                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1520                                 if (vsbuffer)
1521                                 {
1522                                         vsbinsize = vsbuffer->GetBufferSize();
1523                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1524                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1525                                         vsbuffer->Release();
1526                                 }
1527                                 if (vslog)
1528                                 {
1529                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1530                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1531                                         vslog->Release();
1532                                 }
1533                         }
1534                         if (fragstring && fragstring[0])
1535                         {
1536                                 if (debugshader)
1537                                 {
1538 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1539 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1540                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1541                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1542                                 }
1543                                 else
1544                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1545                                 if (psbuffer)
1546                                 {
1547                                         psbinsize = psbuffer->GetBufferSize();
1548                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1549                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1550                                         psbuffer->Release();
1551                                 }
1552                                 if (pslog)
1553                                 {
1554                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1555                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1556                                         pslog->Release();
1557                                 }
1558                         }
1559                         Sys_UnloadLibrary(&d3dx9_dll);
1560                 }
1561                 else
1562                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1563         }
1564         if (vsbin && psbin)
1565         {
1566                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1567                 if (FAILED(vsresult))
1568                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1569                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1570                 if (FAILED(psresult))
1571                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1572         }
1573         // free the shader data
1574         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1575         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1576 }
1577
1578 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1579 {
1580         int i;
1581         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1582         int vertstring_length = 0;
1583         int geomstring_length = 0;
1584         int fragstring_length = 0;
1585         char *t;
1586         char *vertexstring, *geometrystring, *fragmentstring;
1587         char *vertstring, *geomstring, *fragstring;
1588         char permutationname[256];
1589         char cachename[256];
1590         int vertstrings_count = 0;
1591         int geomstrings_count = 0;
1592         int fragstrings_count = 0;
1593         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596
1597         if (p->compiled)
1598                 return;
1599         p->compiled = true;
1600         p->vertexshader = NULL;
1601         p->pixelshader = NULL;
1602
1603         permutationname[0] = 0;
1604         cachename[0] = 0;
1605         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1606         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1607         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1608
1609         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1610         strlcat(cachename, "hlsl/", sizeof(cachename));
1611
1612         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1613         vertstrings_count = 0;
1614         geomstrings_count = 0;
1615         fragstrings_count = 0;
1616         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1617         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1618         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1619
1620         // the first pretext is which type of shader to compile as
1621         // (later these will all be bound together as a program object)
1622         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1623         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1624         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1625
1626         // the second pretext is the mode (for example a light source)
1627         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1628         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1629         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1630         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1631         strlcat(cachename, modeinfo->name, sizeof(cachename));
1632
1633         // now add all the permutation pretexts
1634         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1635         {
1636                 if (permutation & (1<<i))
1637                 {
1638                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1642                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1643                 }
1644                 else
1645                 {
1646                         // keep line numbers correct
1647                         vertstrings_list[vertstrings_count++] = "\n";
1648                         geomstrings_list[geomstrings_count++] = "\n";
1649                         fragstrings_list[fragstrings_count++] = "\n";
1650                 }
1651         }
1652
1653         // add static parms
1654         R_CompileShader_AddStaticParms(mode, permutation);
1655         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1656         vertstrings_count += shaderstaticparms_count;
1657         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         geomstrings_count += shaderstaticparms_count;
1659         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660         fragstrings_count += shaderstaticparms_count;
1661
1662         // replace spaces in the cachename with _ characters
1663         for (i = 0;cachename[i];i++)
1664                 if (cachename[i] == ' ')
1665                         cachename[i] = '_';
1666
1667         // now append the shader text itself
1668         vertstrings_list[vertstrings_count++] = vertexstring;
1669         geomstrings_list[geomstrings_count++] = geometrystring;
1670         fragstrings_list[fragstrings_count++] = fragmentstring;
1671
1672         // if any sources were NULL, clear the respective list
1673         if (!vertexstring)
1674                 vertstrings_count = 0;
1675         if (!geometrystring)
1676                 geomstrings_count = 0;
1677         if (!fragmentstring)
1678                 fragstrings_count = 0;
1679
1680         vertstring_length = 0;
1681         for (i = 0;i < vertstrings_count;i++)
1682                 vertstring_length += strlen(vertstrings_list[i]);
1683         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1684         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1685                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1686
1687         geomstring_length = 0;
1688         for (i = 0;i < geomstrings_count;i++)
1689                 geomstring_length += strlen(geomstrings_list[i]);
1690         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1691         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1692                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1693
1694         fragstring_length = 0;
1695         for (i = 0;i < fragstrings_count;i++)
1696                 fragstring_length += strlen(fragstrings_list[i]);
1697         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1698         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1699                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1700
1701         // try to load the cached shader, or generate one
1702         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1703
1704         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1705                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1706         else
1707                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1708
1709         // free the strings
1710         if (vertstring)
1711                 Mem_Free(vertstring);
1712         if (geomstring)
1713                 Mem_Free(geomstring);
1714         if (fragstring)
1715                 Mem_Free(fragstring);
1716         if (vertexstring)
1717                 Mem_Free(vertexstring);
1718         if (geometrystring)
1719                 Mem_Free(geometrystring);
1720         if (fragmentstring)
1721                 Mem_Free(fragmentstring);
1722 }
1723
1724 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1725 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1726 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);}
1727 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);}
1728 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);}
1729 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);}
1730
1731 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1737
1738 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1739 {
1740         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1741         if (r_hlsl_permutation != perm)
1742         {
1743                 r_hlsl_permutation = perm;
1744                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1745                 {
1746                         if (!r_hlsl_permutation->compiled)
1747                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1748                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1749                         {
1750                                 // remove features until we find a valid permutation
1751                                 int i;
1752                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1753                                 {
1754                                         // reduce i more quickly whenever it would not remove any bits
1755                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1756                                         if (!(permutation & j))
1757                                                 continue;
1758                                         permutation -= j;
1759                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1760                                         if (!r_hlsl_permutation->compiled)
1761                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1762                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1763                                                 break;
1764                                 }
1765                                 if (i >= SHADERPERMUTATION_COUNT)
1766                                 {
1767                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1768                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1769                                         return; // no bit left to clear, entire mode is broken
1770                                 }
1771                         }
1772                 }
1773                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1774                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1775         }
1776         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1777         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1778         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1779 }
1780 #endif
1781
1782 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1783 {
1784         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1785         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1786         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1787         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1788 }
1789
1790 static void R_GLSL_Restart_f(void)
1791 {
1792         unsigned int i, limit;
1793         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1794                 Mem_Free(glslshaderstring);
1795         glslshaderstring = NULL;
1796         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1797                 Mem_Free(hlslshaderstring);
1798         hlslshaderstring = NULL;
1799         switch(vid.renderpath)
1800         {
1801         case RENDERPATH_D3D9:
1802 #ifdef SUPPORTD3D
1803                 {
1804                         r_hlsl_permutation_t *p;
1805                         r_hlsl_permutation = NULL;
1806                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1807                         for (i = 0;i < limit;i++)
1808                         {
1809                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1810                                 {
1811                                         if (p->vertexshader)
1812                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1813                                         if (p->pixelshader)
1814                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1815                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1816                                 }
1817                         }
1818                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1819                 }
1820 #endif
1821                 break;
1822         case RENDERPATH_D3D10:
1823                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1824                 break;
1825         case RENDERPATH_D3D11:
1826                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1827                 break;
1828         case RENDERPATH_GL20:
1829         case RENDERPATH_GLES2:
1830                 {
1831                         r_glsl_permutation_t *p;
1832                         r_glsl_permutation = NULL;
1833                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1834                         for (i = 0;i < limit;i++)
1835                         {
1836                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1837                                 {
1838                                         GL_Backend_FreeProgram(p->program);
1839                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1840                                 }
1841                         }
1842                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1843                 }
1844                 break;
1845         case RENDERPATH_GL11:
1846         case RENDERPATH_GL13:
1847         case RENDERPATH_GLES1:
1848                 break;
1849         case RENDERPATH_SOFT:
1850                 break;
1851         }
1852 }
1853
1854 static void R_GLSL_DumpShader_f(void)
1855 {
1856         int i;
1857         qfile_t *file;
1858
1859         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1860         if (file)
1861         {
1862                 FS_Print(file, "/* The engine may define the following macros:\n");
1863                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864                 for (i = 0;i < SHADERMODE_COUNT;i++)
1865                         FS_Print(file, glslshadermodeinfo[i].pretext);
1866                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867                         FS_Print(file, shaderpermutationinfo[i].pretext);
1868                 FS_Print(file, "*/\n");
1869                 FS_Print(file, builtinshaderstring);
1870                 FS_Close(file);
1871                 Con_Printf("glsl/default.glsl written\n");
1872         }
1873         else
1874                 Con_Printf("failed to write to glsl/default.glsl\n");
1875
1876         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1877         if (file)
1878         {
1879                 FS_Print(file, "/* The engine may define the following macros:\n");
1880                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1881                 for (i = 0;i < SHADERMODE_COUNT;i++)
1882                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1883                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884                         FS_Print(file, shaderpermutationinfo[i].pretext);
1885                 FS_Print(file, "*/\n");
1886                 FS_Print(file, builtinhlslshaderstring);
1887                 FS_Close(file);
1888                 Con_Printf("hlsl/default.hlsl written\n");
1889         }
1890         else
1891                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1892 }
1893
1894 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1895 {
1896         unsigned int permutation = 0;
1897         if (r_trippy.integer && !notrippy)
1898                 permutation |= SHADERPERMUTATION_TRIPPY;
1899         permutation |= SHADERPERMUTATION_VIEWTINT;
1900         if (first)
1901                 permutation |= SHADERPERMUTATION_DIFFUSE;
1902         if (second)
1903                 permutation |= SHADERPERMUTATION_SPECULAR;
1904         if (texturemode == GL_MODULATE)
1905                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1906         else if (texturemode == GL_ADD)
1907                 permutation |= SHADERPERMUTATION_GLOW;
1908         else if (texturemode == GL_DECAL)
1909                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1910         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1911                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1912         if (suppresstexalpha)
1913                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1914         if (!second)
1915                 texturemode = GL_MODULATE;
1916         if (vid.allowalphatocoverage)
1917                 GL_AlphaToCoverage(false);
1918         switch (vid.renderpath)
1919         {
1920         case RENDERPATH_D3D9:
1921 #ifdef SUPPORTD3D
1922                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1923                 R_Mesh_TexBind(GL20TU_FIRST , first );
1924                 R_Mesh_TexBind(GL20TU_SECOND, second);
1925                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1926                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1927 #endif
1928                 break;
1929         case RENDERPATH_D3D10:
1930                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_D3D11:
1933                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934                 break;
1935         case RENDERPATH_GL20:
1936         case RENDERPATH_GLES2:
1937                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1938                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1939                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1940                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1941                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1942                 break;
1943         case RENDERPATH_GL13:
1944         case RENDERPATH_GLES1:
1945                 R_Mesh_TexBind(0, first );
1946                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1947                 R_Mesh_TexBind(1, second);
1948                 if (second)
1949                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1950                 break;
1951         case RENDERPATH_GL11:
1952                 R_Mesh_TexBind(0, first );
1953                 break;
1954         case RENDERPATH_SOFT:
1955                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1956                 R_Mesh_TexBind(GL20TU_FIRST , first );
1957                 R_Mesh_TexBind(GL20TU_SECOND, second);
1958                 break;
1959         }
1960 }
1961
1962 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1963 {
1964         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1965 }
1966
1967 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1968 {
1969         unsigned int permutation = 0;
1970         if (r_trippy.integer && !notrippy)
1971                 permutation |= SHADERPERMUTATION_TRIPPY;
1972         if (vid.allowalphatocoverage)
1973                 GL_AlphaToCoverage(false);
1974         switch (vid.renderpath)
1975         {
1976         case RENDERPATH_D3D9:
1977 #ifdef SUPPORTD3D
1978                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1979 #endif
1980                 break;
1981         case RENDERPATH_D3D10:
1982                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983                 break;
1984         case RENDERPATH_D3D11:
1985                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_GL20:
1988         case RENDERPATH_GLES2:
1989                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1990                 break;
1991         case RENDERPATH_GL13:
1992         case RENDERPATH_GLES1:
1993                 R_Mesh_TexBind(0, 0);
1994                 R_Mesh_TexBind(1, 0);
1995                 break;
1996         case RENDERPATH_GL11:
1997                 R_Mesh_TexBind(0, 0);
1998                 break;
1999         case RENDERPATH_SOFT:
2000                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2001                 break;
2002         }
2003 }
2004
2005 void R_SetupShader_ShowDepth(qboolean notrippy)
2006 {
2007         int permutation = 0;
2008         if (r_trippy.integer && !notrippy)
2009                 permutation |= SHADERPERMUTATION_TRIPPY;
2010         if (vid.allowalphatocoverage)
2011                 GL_AlphaToCoverage(false);
2012         switch (vid.renderpath)
2013         {
2014         case RENDERPATH_D3D9:
2015 #ifdef SUPPORTHLSL
2016                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2017 #endif
2018                 break;
2019         case RENDERPATH_D3D10:
2020                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2021                 break;
2022         case RENDERPATH_D3D11:
2023                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2024                 break;
2025         case RENDERPATH_GL20:
2026         case RENDERPATH_GLES2:
2027                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2028                 break;
2029         case RENDERPATH_GL13:
2030         case RENDERPATH_GLES1:
2031                 break;
2032         case RENDERPATH_GL11:
2033                 break;
2034         case RENDERPATH_SOFT:
2035                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2036                 break;
2037         }
2038 }
2039
2040 extern qboolean r_shadow_usingdeferredprepass;
2041 extern rtexture_t *r_shadow_attenuationgradienttexture;
2042 extern rtexture_t *r_shadow_attenuation2dtexture;
2043 extern rtexture_t *r_shadow_attenuation3dtexture;
2044 extern qboolean r_shadow_usingshadowmap2d;
2045 extern qboolean r_shadow_usingshadowmaportho;
2046 extern float r_shadow_shadowmap_texturescale[2];
2047 extern float r_shadow_shadowmap_parameters[4];
2048 extern qboolean r_shadow_shadowmapvsdct;
2049 extern qboolean r_shadow_shadowmapsampler;
2050 extern int r_shadow_shadowmappcf;
2051 extern rtexture_t *r_shadow_shadowmap2dtexture;
2052 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2053 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2054 extern matrix4x4_t r_shadow_shadowmapmatrix;
2055 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2056 extern int r_shadow_prepass_width;
2057 extern int r_shadow_prepass_height;
2058 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2059 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2060 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2061 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2062 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2063
2064 #define BLENDFUNC_ALLOWS_COLORMOD      1
2065 #define BLENDFUNC_ALLOWS_FOG           2
2066 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2067 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2068 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2069 static int R_BlendFuncFlags(int src, int dst)
2070 {
2071         int r = 0;
2072
2073         // a blendfunc allows colormod if:
2074         // a) it can never keep the destination pixel invariant, or
2075         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2076         // this is to prevent unintended side effects from colormod
2077
2078         // a blendfunc allows fog if:
2079         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2080         // this is to prevent unintended side effects from fog
2081
2082         // these checks are the output of fogeval.pl
2083
2084         r |= BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2093         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2094         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2097         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2106
2107         return r;
2108 }
2109
2110 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)
2111 {
2112         // select a permutation of the lighting shader appropriate to this
2113         // combination of texture, entity, light source, and fogging, only use the
2114         // minimum features necessary to avoid wasting rendering time in the
2115         // fragment shader on features that are not being used
2116         unsigned int permutation = 0;
2117         unsigned int mode = 0;
2118         int blendfuncflags;
2119         static float dummy_colormod[3] = {1, 1, 1};
2120         float *colormod = rsurface.colormod;
2121         float m16f[16];
2122         matrix4x4_t tempmatrix;
2123         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2124         if (r_trippy.integer && !notrippy)
2125                 permutation |= SHADERPERMUTATION_TRIPPY;
2126         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2127                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2128         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2129                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2130         if (rsurfacepass == RSURFPASS_BACKGROUND)
2131         {
2132                 // distorted background
2133                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2134                 {
2135                         mode = SHADERMODE_WATER;
2136                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2137                         {
2138                                 // this is the right thing to do for wateralpha
2139                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2140                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2141                         }
2142                         else
2143                         {
2144                                 // this is the right thing to do for entity alpha
2145                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                         }
2148                 }
2149                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2150                 {
2151                         mode = SHADERMODE_REFRACTION;
2152                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                 }
2155                 else
2156                 {
2157                         mode = SHADERMODE_GENERIC;
2158                         permutation |= SHADERPERMUTATION_DIFFUSE;
2159                         GL_BlendFunc(GL_ONE, GL_ZERO);
2160                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2161                 }
2162                 if (vid.allowalphatocoverage)
2163                         GL_AlphaToCoverage(false);
2164         }
2165         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2166         {
2167                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2168                 {
2169                         switch(rsurface.texture->offsetmapping)
2170                         {
2171                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2172                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2173                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2174                         case OFFSETMAPPING_OFF: break;
2175                         }
2176                 }
2177                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2178                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2179                 // normalmap (deferred prepass), may use alpha test on diffuse
2180                 mode = SHADERMODE_DEFERREDGEOMETRY;
2181                 GL_BlendFunc(GL_ONE, GL_ZERO);
2182                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2183                 if (vid.allowalphatocoverage)
2184                         GL_AlphaToCoverage(false);
2185         }
2186         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2187         {
2188                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2189                 {
2190                         switch(rsurface.texture->offsetmapping)
2191                         {
2192                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2193                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2194                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_OFF: break;
2196                         }
2197                 }
2198                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200                 // light source
2201                 mode = SHADERMODE_LIGHTSOURCE;
2202                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2203                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2204                 if (diffusescale > 0)
2205                         permutation |= SHADERPERMUTATION_DIFFUSE;
2206                 if (specularscale > 0)
2207                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2208                 if (r_refdef.fogenabled)
2209                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2210                 if (rsurface.texture->colormapping)
2211                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2212                 if (r_shadow_usingshadowmap2d)
2213                 {
2214                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2215                         if(r_shadow_shadowmapvsdct)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2217
2218                         if (r_shadow_shadowmapsampler)
2219                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2220                         if (r_shadow_shadowmappcf > 1)
2221                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2222                         else if (r_shadow_shadowmappcf)
2223                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2224                 }
2225                 if (rsurface.texture->reflectmasktexture)
2226                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2227                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2228                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2229                 if (vid.allowalphatocoverage)
2230                         GL_AlphaToCoverage(false);
2231         }
2232         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2233         {
2234                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2235                 {
2236                         switch(rsurface.texture->offsetmapping)
2237                         {
2238                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2239                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_OFF: break;
2242                         }
2243                 }
2244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2245                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2246                 // unshaded geometry (fullbright or ambient model lighting)
2247                 mode = SHADERMODE_FLATCOLOR;
2248                 ambientscale = diffusescale = specularscale = 0;
2249                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2250                         permutation |= SHADERPERMUTATION_GLOW;
2251                 if (r_refdef.fogenabled)
2252                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2253                 if (rsurface.texture->colormapping)
2254                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2255                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2256                 {
2257                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2258                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2259
2260                         if (r_shadow_shadowmapsampler)
2261                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2262                         if (r_shadow_shadowmappcf > 1)
2263                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2264                         else if (r_shadow_shadowmappcf)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2266                 }
2267                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2268                         permutation |= SHADERPERMUTATION_REFLECTION;
2269                 if (rsurface.texture->reflectmasktexture)
2270                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2271                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2272                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2273                 // when using alphatocoverage, we don't need alphakill
2274                 if (vid.allowalphatocoverage)
2275                 {
2276                         if (r_transparent_alphatocoverage.integer)
2277                         {
2278                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2279                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2280                         }
2281                         else
2282                                 GL_AlphaToCoverage(false);
2283                 }
2284         }
2285         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2286         {
2287                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2288                 {
2289                         switch(rsurface.texture->offsetmapping)
2290                         {
2291                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2292                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2293                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294                         case OFFSETMAPPING_OFF: break;
2295                         }
2296                 }
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2298                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2299                 // directional model lighting
2300                 mode = SHADERMODE_LIGHTDIRECTION;
2301                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302                         permutation |= SHADERPERMUTATION_GLOW;
2303                 permutation |= SHADERPERMUTATION_DIFFUSE;
2304                 if (specularscale > 0)
2305                         permutation |= SHADERPERMUTATION_SPECULAR;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314
2315                         if (r_shadow_shadowmapsampler)
2316                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2317                         if (r_shadow_shadowmappcf > 1)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2319                         else if (r_shadow_shadowmappcf)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2321                 }
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323                         permutation |= SHADERPERMUTATION_REFLECTION;
2324                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326                 if (rsurface.texture->reflectmasktexture)
2327                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2329                 {
2330                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331                         if (r_shadow_bouncegriddirectional)
2332                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333                 }
2334                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336                 // when using alphatocoverage, we don't need alphakill
2337                 if (vid.allowalphatocoverage)
2338                 {
2339                         if (r_transparent_alphatocoverage.integer)
2340                         {
2341                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2342                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2343                         }
2344                         else
2345                                 GL_AlphaToCoverage(false);
2346                 }
2347         }
2348         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2349         {
2350                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2351                 {
2352                         switch(rsurface.texture->offsetmapping)
2353                         {
2354                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2355                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2356                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2357                         case OFFSETMAPPING_OFF: break;
2358                         }
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2362                 // ambient model lighting
2363                 mode = SHADERMODE_LIGHTDIRECTION;
2364                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2365                         permutation |= SHADERPERMUTATION_GLOW;
2366                 if (r_refdef.fogenabled)
2367                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2368                 if (rsurface.texture->colormapping)
2369                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2370                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2371                 {
2372                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2373                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2374
2375                         if (r_shadow_shadowmapsampler)
2376                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2377                         if (r_shadow_shadowmappcf > 1)
2378                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2379                         else if (r_shadow_shadowmappcf)
2380                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2381                 }
2382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2383                         permutation |= SHADERPERMUTATION_REFLECTION;
2384                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2385                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2386                 if (rsurface.texture->reflectmasktexture)
2387                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2388                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2389                 {
2390                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2391                         if (r_shadow_bouncegriddirectional)
2392                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2393                 }
2394                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2395                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2396                 // when using alphatocoverage, we don't need alphakill
2397                 if (vid.allowalphatocoverage)
2398                 {
2399                         if (r_transparent_alphatocoverage.integer)
2400                         {
2401                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2402                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2403                         }
2404                         else
2405                                 GL_AlphaToCoverage(false);
2406                 }
2407         }
2408         else
2409         {
2410                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2411                 {
2412                         switch(rsurface.texture->offsetmapping)
2413                         {
2414                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2415                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2416                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2417                         case OFFSETMAPPING_OFF: break;
2418                         }
2419                 }
2420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2421                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2422                 // lightmapped wall
2423                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2424                         permutation |= SHADERPERMUTATION_GLOW;
2425                 if (r_refdef.fogenabled)
2426                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2427                 if (rsurface.texture->colormapping)
2428                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2429                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2430                 {
2431                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2432                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2433
2434                         if (r_shadow_shadowmapsampler)
2435                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2436                         if (r_shadow_shadowmappcf > 1)
2437                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2438                         else if (r_shadow_shadowmappcf)
2439                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2440                 }
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2442                         permutation |= SHADERPERMUTATION_REFLECTION;
2443                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2444                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2445                 if (rsurface.texture->reflectmasktexture)
2446                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2447                 if (FAKELIGHT_ENABLED)
2448                 {
2449                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2450                         mode = SHADERMODE_FAKELIGHT;
2451                         permutation |= SHADERPERMUTATION_DIFFUSE;
2452                         if (specularscale > 0)
2453                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2454                 }
2455                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2456                 {
2457                         // deluxemapping (light direction texture)
2458                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2459                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2460                         else
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2462                         permutation |= SHADERPERMUTATION_DIFFUSE;
2463                         if (specularscale > 0)
2464                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2465                 }
2466                 else if (r_glsl_deluxemapping.integer >= 2)
2467                 {
2468                         // fake deluxemapping (uniform light direction in tangentspace)
2469                         if (rsurface.uselightmaptexture)
2470                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2471                         else
2472                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2473                         permutation |= SHADERPERMUTATION_DIFFUSE;
2474                         if (specularscale > 0)
2475                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2476                 }
2477                 else if (rsurface.uselightmaptexture)
2478                 {
2479                         // ordinary lightmapping (q1bsp, q3bsp)
2480                         mode = SHADERMODE_LIGHTMAP;
2481                 }
2482                 else
2483                 {
2484                         // ordinary vertex coloring (q3bsp)
2485                         mode = SHADERMODE_VERTEXCOLOR;
2486                 }
2487                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2488                 {
2489                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2490                         if (r_shadow_bouncegriddirectional)
2491                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2492                 }
2493                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2495                 // when using alphatocoverage, we don't need alphakill
2496                 if (vid.allowalphatocoverage)
2497                 {
2498                         if (r_transparent_alphatocoverage.integer)
2499                         {
2500                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2501                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2502                         }
2503                         else
2504                                 GL_AlphaToCoverage(false);
2505                 }
2506         }
2507         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2508                 colormod = dummy_colormod;
2509         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2510                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2511         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2512                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2513         switch(vid.renderpath)
2514         {
2515         case RENDERPATH_D3D9:
2516 #ifdef SUPPORTD3D
2517                 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);
2518                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2519                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2520                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2521                 if (mode == SHADERMODE_LIGHTSOURCE)
2522                 {
2523                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2524                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2525                 }
2526                 else
2527                 {
2528                         if (mode == SHADERMODE_LIGHTDIRECTION)
2529                         {
2530                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2531                         }
2532                 }
2533                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2534                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2535                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2536                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2537                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2538
2539                 if (mode == SHADERMODE_LIGHTSOURCE)
2540                 {
2541                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2546
2547                         // additive passes are only darkened by fog, not tinted
2548                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2549                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2550                 }
2551                 else
2552                 {
2553                         if (mode == SHADERMODE_FLATCOLOR)
2554                         {
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2556                         }
2557                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2558                         {
2559                                 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]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2561                                 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);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2566                         }
2567                         else
2568                         {
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2571                                 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);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2574                         }
2575                         // additive passes are only darkened by fog, not tinted
2576                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2578                         else
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2580                         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);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2587                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2588                         if (mode == SHADERMODE_WATER)
2589                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2590                 }
2591                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2592                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2593                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2594                 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));
2595                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2596                 if (rsurface.texture->pantstexture)
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2598                 else
2599                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2600                 if (rsurface.texture->shirttexture)
2601                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2602                 else
2603                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2604                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2608                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2609                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2610                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2612                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2613                         );
2614                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2616                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2617                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2618
2619                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2620                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2621                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2622                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2624                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2625                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2626                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2627                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2628                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2629                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2630                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2631                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2632                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2633                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2634                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2635                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2636                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2637                 {
2638                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2639                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2640                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641                 }
2642                 else
2643                 {
2644                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2645                 }
2646 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2647 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2648                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2649                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2650                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2651                 {
2652                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2653                         if (rsurface.rtlight)
2654                         {
2655                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2656                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2657                         }
2658                 }
2659 #endif
2660                 break;
2661         case RENDERPATH_D3D10:
2662                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2663                 break;
2664         case RENDERPATH_D3D11:
2665                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2666                 break;
2667         case RENDERPATH_GL20:
2668         case RENDERPATH_GLES2:
2669                 if (!vid.useinterleavedarrays)
2670                 {
2671                         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);
2672                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2673                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2679                 }
2680                 else
2681                 {
2682                         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);
2683                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2684                 }
2685                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2686                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2687                 if (mode == SHADERMODE_LIGHTSOURCE)
2688                 {
2689                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2690                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2691                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2692                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2693                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2694                         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);
2695         
2696                         // additive passes are only darkened by fog, not tinted
2697                         if (r_glsl_permutation->loc_FogColor >= 0)
2698                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2699                         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);
2700                 }
2701                 else
2702                 {
2703                         if (mode == SHADERMODE_FLATCOLOR)
2704                         {
2705                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2706                         }
2707                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2708                         {
2709                                 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]);
2710                                 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]);
2711                                 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);
2712                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2713                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2714                                 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]);
2715                                 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]);
2716                         }
2717                         else
2718                         {
2719                                 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]);
2720                                 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]);
2721                                 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);
2722                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2723                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2724                         }
2725                         // additive passes are only darkened by fog, not tinted
2726                         if (r_glsl_permutation->loc_FogColor >= 0)
2727                         {
2728                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2729                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2730                                 else
2731                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2732                         }
2733                         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);
2734                         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]);
2735                         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]);
2736                         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]);
2737                         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]);
2738                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2739                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2740                         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);
2741                         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]);
2742                 }
2743                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2744                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2745                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2746                 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]);
2747                 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]);
2748
2749                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2750                 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));
2751                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2752                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2753                 {
2754                         if (rsurface.texture->pantstexture)
2755                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2756                         else
2757                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2758                 }
2759                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2760                 {
2761                         if (rsurface.texture->shirttexture)
2762                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2763                         else
2764                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2765                 }
2766                 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]);
2767                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2768                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2769                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2770                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2771                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2772                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2773                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2774                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2775                         );
2776                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2777                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2778                 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]);
2779                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2780                 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);}
2781                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2782
2783                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2784                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2785                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2786                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2787                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2788                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2789                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2790                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2791                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2794                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2795                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2796                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2797                 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);
2798                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2799                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2800                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2801                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2802                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2803                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2804                 {
2805                         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);
2806                         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);
2807                         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);
2808                 }
2809                 else
2810                 {
2811                         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);
2812                 }
2813                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2814                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2815                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2816                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2817                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2818                 {
2819                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2820                         if (rsurface.rtlight)
2821                         {
2822                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2823                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2824                         }
2825                 }
2826                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2827                 CHECKGLERROR
2828                 break;
2829         case RENDERPATH_GL11:
2830         case RENDERPATH_GL13:
2831         case RENDERPATH_GLES1:
2832                 break;
2833         case RENDERPATH_SOFT:
2834                 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);
2835                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2836                 R_SetupShader_SetPermutationSoft(mode, permutation);
2837                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2838                 if (mode == SHADERMODE_LIGHTSOURCE)
2839                 {
2840                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2846         
2847                         // additive passes are only darkened by fog, not tinted
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2849                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2850                 }
2851                 else
2852                 {
2853                         if (mode == SHADERMODE_FLATCOLOR)
2854                         {
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2856                         }
2857                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2858                         {
2859                                 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]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2861                                 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);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2864                                 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]);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2866                         }
2867                         else
2868                         {
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2871                                 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);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2874                         }
2875                         // additive passes are only darkened by fog, not tinted
2876                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2878                         else
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2880                         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);
2881                         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]);
2882                         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]);
2883                         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]);
2884                         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]);
2885                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2886                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2888                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2889                 }
2890                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2891                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2892                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2893                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2894                 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]);
2895
2896                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2897                 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));
2898                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2899                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2900                 {
2901                         if (rsurface.texture->pantstexture)
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2903                         else
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2905                 }
2906                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2907                 {
2908                         if (rsurface.texture->shirttexture)
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2910                         else
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2912                 }
2913                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2917                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2918                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2919                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2920                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2921                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2922                         );
2923                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2924                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2927
2928                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2929                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2930                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2931                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2936                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2938                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2940                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2941                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2942                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2943                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2944                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2945                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2946                 {
2947                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2948                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2949                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2950                 }
2951                 else
2952                 {
2953                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2954                 }
2955 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2959                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2960                 {
2961                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2962                         if (rsurface.rtlight)
2963                         {
2964                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2965                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2966                         }
2967                 }
2968                 break;
2969         }
2970 }
2971
2972 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2973 {
2974         // select a permutation of the lighting shader appropriate to this
2975         // combination of texture, entity, light source, and fogging, only use the
2976         // minimum features necessary to avoid wasting rendering time in the
2977         // fragment shader on features that are not being used
2978         unsigned int permutation = 0;
2979         unsigned int mode = 0;
2980         const float *lightcolorbase = rtlight->currentcolor;
2981         float ambientscale = rtlight->ambientscale;
2982         float diffusescale = rtlight->diffusescale;
2983         float specularscale = rtlight->specularscale;
2984         // this is the location of the light in view space
2985         vec3_t viewlightorigin;
2986         // this transforms from view space (camera) to light space (cubemap)
2987         matrix4x4_t viewtolight;
2988         matrix4x4_t lighttoview;
2989         float viewtolight16f[16];
2990         // light source
2991         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2992         if (rtlight->currentcubemap != r_texture_whitecube)
2993                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2994         if (diffusescale > 0)
2995                 permutation |= SHADERPERMUTATION_DIFFUSE;
2996         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2997                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2998         if (r_shadow_usingshadowmap2d)
2999         {
3000                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3001                 if (r_shadow_shadowmapvsdct)
3002                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3003
3004                 if (r_shadow_shadowmapsampler)
3005                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3006                 if (r_shadow_shadowmappcf > 1)
3007                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3008                 else if (r_shadow_shadowmappcf)
3009                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3010         }
3011         if (vid.allowalphatocoverage)
3012                 GL_AlphaToCoverage(false);
3013         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3014         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3015         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3016         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3017         switch(vid.renderpath)
3018         {
3019         case RENDERPATH_D3D9:
3020 #ifdef SUPPORTD3D
3021                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3022                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3023                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3027                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3028                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3029                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3030                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3031                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3032
3033                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3034                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3035                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3036                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3037                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3038                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3039 #endif
3040                 break;
3041         case RENDERPATH_D3D10:
3042                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3043                 break;
3044         case RENDERPATH_D3D11:
3045                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3046                 break;
3047         case RENDERPATH_GL20:
3048         case RENDERPATH_GLES2:
3049                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3050                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3051                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3052                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3053                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3054                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3055                 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]);
3056                 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]);
3057                 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);
3058                 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]);
3059                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3060
3061                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3062                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3063                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3064                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3065                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3066                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3067                 break;
3068         case RENDERPATH_GL11:
3069         case RENDERPATH_GL13:
3070         case RENDERPATH_GLES1:
3071                 break;
3072         case RENDERPATH_SOFT:
3073                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3074                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3075                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3079                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3080                 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]);
3081                 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);
3082                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3083                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3084
3085                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3086                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3087                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3088                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3089                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3090                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3091                 break;
3092         }
3093 }
3094
3095 #define SKINFRAME_HASH 1024
3096
3097 typedef struct
3098 {
3099         int loadsequence; // incremented each level change
3100         memexpandablearray_t array;
3101         skinframe_t *hash[SKINFRAME_HASH];
3102 }
3103 r_skinframe_t;
3104 r_skinframe_t r_skinframe;
3105
3106 void R_SkinFrame_PrepareForPurge(void)
3107 {
3108         r_skinframe.loadsequence++;
3109         // wrap it without hitting zero
3110         if (r_skinframe.loadsequence >= 200)
3111                 r_skinframe.loadsequence = 1;
3112 }
3113
3114 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3115 {
3116         if (!skinframe)
3117                 return;
3118         // mark the skinframe as used for the purging code
3119         skinframe->loadsequence = r_skinframe.loadsequence;
3120 }
3121
3122 void R_SkinFrame_Purge(void)
3123 {
3124         int i;
3125         skinframe_t *s;
3126         for (i = 0;i < SKINFRAME_HASH;i++)
3127         {
3128                 for (s = r_skinframe.hash[i];s;s = s->next)
3129                 {
3130                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3131                         {
3132                                 if (s->merged == s->base)
3133                                         s->merged = NULL;
3134                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3135                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3136                                 R_PurgeTexture(s->merged);s->merged = NULL;
3137                                 R_PurgeTexture(s->base  );s->base   = NULL;
3138                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3139                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3140                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3141                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3142                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3143                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3144                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3145                                 s->loadsequence = 0;
3146                         }
3147                 }
3148         }
3149 }
3150
3151 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3152         skinframe_t *item;
3153         char basename[MAX_QPATH];
3154
3155         Image_StripImageExtension(name, basename, sizeof(basename));
3156
3157         if( last == NULL ) {
3158                 int hashindex;
3159                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3160                 item = r_skinframe.hash[hashindex];
3161         } else {
3162                 item = last->next;
3163         }
3164
3165         // linearly search through the hash bucket
3166         for( ; item ; item = item->next ) {
3167                 if( !strcmp( item->basename, basename ) ) {
3168                         return item;
3169                 }
3170         }
3171         return NULL;
3172 }
3173
3174 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3175 {
3176         skinframe_t *item;
3177         int hashindex;
3178         char basename[MAX_QPATH];
3179
3180         Image_StripImageExtension(name, basename, sizeof(basename));
3181
3182         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3183         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3184                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3185                         break;
3186
3187         if (!item) {
3188                 rtexture_t *dyntexture;
3189                 // check whether its a dynamic texture
3190                 dyntexture = CL_GetDynTexture( basename );
3191                 if (!add && !dyntexture)
3192                         return NULL;
3193                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3194                 memset(item, 0, sizeof(*item));
3195                 strlcpy(item->basename, basename, sizeof(item->basename));
3196                 item->base = dyntexture; // either NULL or dyntexture handle
3197                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3198                 item->comparewidth = comparewidth;
3199                 item->compareheight = compareheight;
3200                 item->comparecrc = comparecrc;
3201                 item->next = r_skinframe.hash[hashindex];
3202                 r_skinframe.hash[hashindex] = item;
3203         }
3204         else if (textureflags & TEXF_FORCE_RELOAD)
3205         {
3206                 rtexture_t *dyntexture;
3207                 // check whether its a dynamic texture
3208                 dyntexture = CL_GetDynTexture( basename );
3209                 if (!add && !dyntexture)
3210                         return NULL;
3211                 if (item->merged == item->base)
3212                         item->merged = NULL;
3213                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3214                 R_PurgeTexture(item->stain );item->stain  = NULL;
3215                 R_PurgeTexture(item->merged);item->merged = NULL;
3216                 R_PurgeTexture(item->base  );item->base   = NULL;
3217                 R_PurgeTexture(item->pants );item->pants  = NULL;
3218                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3219                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3220                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3221                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3222                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3223         R_PurgeTexture(item->reflect);item->reflect = NULL;
3224                 item->loadsequence = 0;
3225         }
3226         else if( item->base == NULL )
3227         {
3228                 rtexture_t *dyntexture;
3229                 // check whether its a dynamic texture
3230                 // 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]
3231                 dyntexture = CL_GetDynTexture( basename );
3232                 item->base = dyntexture; // either NULL or dyntexture handle
3233         }
3234
3235         R_SkinFrame_MarkUsed(item);
3236         return item;
3237 }
3238
3239 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3240         { \
3241                 unsigned long long avgcolor[5], wsum; \
3242                 int pix, comp, w; \
3243                 avgcolor[0] = 0; \
3244                 avgcolor[1] = 0; \
3245                 avgcolor[2] = 0; \
3246                 avgcolor[3] = 0; \
3247                 avgcolor[4] = 0; \
3248                 wsum = 0; \
3249                 for(pix = 0; pix < cnt; ++pix) \
3250                 { \
3251                         w = 0; \
3252                         for(comp = 0; comp < 3; ++comp) \
3253                                 w += getpixel; \
3254                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3255                         { \
3256                                 ++wsum; \
3257                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3258                                 w = getpixel; \
3259                                 for(comp = 0; comp < 3; ++comp) \
3260                                         avgcolor[comp] += getpixel * w; \
3261                                 avgcolor[3] += w; \
3262                         } \
3263                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3264                         avgcolor[4] += getpixel; \
3265                 } \
3266                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3267                         avgcolor[3] = 1; \
3268                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3269                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3270                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3271                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3272         }
3273
3274 extern cvar_t gl_picmip;
3275 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3276 {
3277         int j;
3278         unsigned char *pixels;
3279         unsigned char *bumppixels;
3280         unsigned char *basepixels = NULL;
3281         int basepixels_width = 0;
3282         int basepixels_height = 0;
3283         skinframe_t *skinframe;
3284         rtexture_t *ddsbase = NULL;
3285         qboolean ddshasalpha = false;
3286         float ddsavgcolor[4];
3287         char basename[MAX_QPATH];
3288         int miplevel = R_PicmipForFlags(textureflags);
3289         int savemiplevel = miplevel;
3290         int mymiplevel;
3291         char vabuf[1024];
3292
3293         if (cls.state == ca_dedicated)
3294                 return NULL;
3295
3296         // return an existing skinframe if already loaded
3297         // if loading of the first image fails, don't make a new skinframe as it
3298         // would cause all future lookups of this to be missing
3299         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3300         if (skinframe && skinframe->base)
3301                 return skinframe;
3302
3303         Image_StripImageExtension(name, basename, sizeof(basename));
3304
3305         // check for DDS texture file first
3306         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3307         {
3308                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3309                 if (basepixels == NULL)
3310                         return NULL;
3311         }
3312
3313         // FIXME handle miplevel
3314
3315         if (developer_loading.integer)
3316                 Con_Printf("loading skin \"%s\"\n", name);
3317
3318         // we've got some pixels to store, so really allocate this new texture now
3319         if (!skinframe)
3320                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3321         textureflags &= ~TEXF_FORCE_RELOAD;
3322         skinframe->stain = NULL;
3323         skinframe->merged = NULL;
3324         skinframe->base = NULL;
3325         skinframe->pants = NULL;
3326         skinframe->shirt = NULL;
3327         skinframe->nmap = NULL;
3328         skinframe->gloss = NULL;
3329         skinframe->glow = NULL;
3330         skinframe->fog = NULL;
3331         skinframe->reflect = NULL;
3332         skinframe->hasalpha = false;
3333
3334         if (ddsbase)
3335         {
3336                 skinframe->base = ddsbase;
3337                 skinframe->hasalpha = ddshasalpha;
3338                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3339                 if (r_loadfog && skinframe->hasalpha)
3340                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3341                 //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]);
3342         }
3343         else
3344         {
3345                 basepixels_width = image_width;
3346                 basepixels_height = image_height;
3347                 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);
3348                 if (textureflags & TEXF_ALPHA)
3349                 {
3350                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3351                         {
3352                                 if (basepixels[j] < 255)
3353                                 {
3354                                         skinframe->hasalpha = true;
3355                                         break;
3356                                 }
3357                         }
3358                         if (r_loadfog && skinframe->hasalpha)
3359                         {
3360                                 // has transparent pixels
3361                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3362                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3363                                 {
3364                                         pixels[j+0] = 255;
3365                                         pixels[j+1] = 255;
3366                                         pixels[j+2] = 255;
3367                                         pixels[j+3] = basepixels[j+3];
3368                                 }
3369                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3370                                 Mem_Free(pixels);
3371                         }
3372                 }
3373                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3374 #ifndef USE_GLES2
3375                 //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]);
3376                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3377                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3378                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3379                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3380 #endif
3381         }
3382
3383         if (r_loaddds)
3384         {
3385                 mymiplevel = savemiplevel;
3386                 if (r_loadnormalmap)
3387                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3388                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3389                 if (r_loadgloss)
3390                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3391                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3392                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3393                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3394         }
3395
3396         // _norm is the name used by tenebrae and has been adopted as standard
3397         if (r_loadnormalmap && skinframe->nmap == NULL)
3398         {
3399                 mymiplevel = savemiplevel;
3400                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3401                 {
3402                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3403                         Mem_Free(pixels);
3404                         pixels = NULL;
3405                 }
3406                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3407                 {
3408                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3409                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3410                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3411                         Mem_Free(pixels);
3412                         Mem_Free(bumppixels);
3413                 }
3414                 else if (r_shadow_bumpscale_basetexture.value > 0)
3415                 {
3416                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3417                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3418                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3419                         Mem_Free(pixels);
3420                 }
3421 #ifndef USE_GLES2
3422                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3423                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3424 #endif
3425         }
3426
3427         // _luma is supported only for tenebrae compatibility
3428         // _glow is the preferred name
3429         mymiplevel = savemiplevel;
3430         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3431         {
3432                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3435                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3436 #endif
3437                 Mem_Free(pixels);pixels = NULL;
3438         }
3439
3440         mymiplevel = savemiplevel;
3441         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3442         {
3443                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3444 #ifndef USE_GLES2
3445                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3446                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3447 #endif
3448                 Mem_Free(pixels);
3449                 pixels = NULL;
3450         }
3451
3452         mymiplevel = savemiplevel;
3453         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3454         {
3455                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3456 #ifndef USE_GLES2
3457                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3458                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3459 #endif
3460                 Mem_Free(pixels);
3461                 pixels = NULL;
3462         }
3463
3464         mymiplevel = savemiplevel;
3465         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3466         {
3467                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3468 #ifndef USE_GLES2
3469                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3470                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3471 #endif
3472                 Mem_Free(pixels);
3473                 pixels = NULL;
3474         }
3475
3476         mymiplevel = savemiplevel;
3477         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3478         {
3479                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3480 #ifndef USE_GLES2
3481                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3482                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3483 #endif
3484                 Mem_Free(pixels);
3485                 pixels = NULL;
3486         }
3487
3488         if (basepixels)
3489                 Mem_Free(basepixels);
3490
3491         return skinframe;
3492 }
3493
3494 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3495 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3496 {
3497         int i;
3498         unsigned char *temp1, *temp2;
3499         skinframe_t *skinframe;
3500         char vabuf[1024];
3501
3502         if (cls.state == ca_dedicated)
3503                 return NULL;
3504
3505         // if already loaded just return it, otherwise make a new skinframe
3506         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3507         if (skinframe && skinframe->base)
3508                 return skinframe;
3509         textureflags &= ~TEXF_FORCE_RELOAD;
3510
3511         skinframe->stain = NULL;
3512         skinframe->merged = NULL;
3513         skinframe->base = NULL;
3514         skinframe->pants = NULL;
3515         skinframe->shirt = NULL;
3516         skinframe->nmap = NULL;
3517         skinframe->gloss = NULL;
3518         skinframe->glow = NULL;
3519         skinframe->fog = NULL;
3520         skinframe->reflect = NULL;
3521         skinframe->hasalpha = false;
3522
3523         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3524         if (!skindata)
3525                 return NULL;
3526
3527         if (developer_loading.integer)
3528                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3529
3530         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3531         {
3532                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3533                 temp2 = temp1 + width * height * 4;
3534                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3535                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3536                 Mem_Free(temp1);
3537         }
3538         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3539         if (textureflags & TEXF_ALPHA)
3540         {
3541                 for (i = 3;i < width * height * 4;i += 4)
3542                 {
3543                         if (skindata[i] < 255)
3544                         {
3545                                 skinframe->hasalpha = true;
3546                                 break;
3547                         }
3548                 }
3549                 if (r_loadfog && skinframe->hasalpha)
3550                 {
3551                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3552                         memcpy(fogpixels, skindata, width * height * 4);
3553                         for (i = 0;i < width * height * 4;i += 4)
3554                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3555                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3556                         Mem_Free(fogpixels);
3557                 }
3558         }
3559
3560         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3561         //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]);
3562
3563         return skinframe;
3564 }
3565
3566 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3567 {
3568         int i;
3569         int featuresmask;
3570         skinframe_t *skinframe;
3571
3572         if (cls.state == ca_dedicated)
3573                 return NULL;
3574
3575         // if already loaded just return it, otherwise make a new skinframe
3576         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3577         if (skinframe && skinframe->base)
3578                 return skinframe;
3579         textureflags &= ~TEXF_FORCE_RELOAD;
3580
3581         skinframe->stain = NULL;
3582         skinframe->merged = NULL;
3583         skinframe->base = NULL;
3584         skinframe->pants = NULL;
3585         skinframe->shirt = NULL;
3586         skinframe->nmap = NULL;
3587         skinframe->gloss = NULL;
3588         skinframe->glow = NULL;
3589         skinframe->fog = NULL;
3590         skinframe->reflect = NULL;
3591         skinframe->hasalpha = false;
3592
3593         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3594         if (!skindata)
3595                 return NULL;
3596
3597         if (developer_loading.integer)
3598                 Con_Printf("loading quake skin \"%s\"\n", name);
3599
3600         // 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)
3601         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3602         memcpy(skinframe->qpixels, skindata, width*height);
3603         skinframe->qwidth = width;
3604         skinframe->qheight = height;
3605
3606         featuresmask = 0;
3607         for (i = 0;i < width * height;i++)
3608                 featuresmask |= palette_featureflags[skindata[i]];
3609
3610         skinframe->hasalpha = false;
3611         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3612         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3613         skinframe->qgeneratemerged = true;
3614         skinframe->qgeneratebase = skinframe->qhascolormapping;
3615         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3616
3617         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3618         //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]);
3619
3620         return skinframe;
3621 }
3622
3623 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3624 {
3625         int width;
3626         int height;
3627         unsigned char *skindata;
3628         char vabuf[1024];
3629
3630         if (!skinframe->qpixels)
3631                 return;
3632
3633         if (!skinframe->qhascolormapping)
3634                 colormapped = false;
3635
3636         if (colormapped)
3637         {
3638                 if (!skinframe->qgeneratebase)
3639                         return;
3640         }
3641         else
3642         {
3643                 if (!skinframe->qgeneratemerged)
3644                         return;
3645         }
3646
3647         width = skinframe->qwidth;
3648         height = skinframe->qheight;
3649         skindata = skinframe->qpixels;
3650
3651         if (skinframe->qgeneratenmap)
3652         {
3653                 unsigned char *temp1, *temp2;
3654                 skinframe->qgeneratenmap = false;
3655                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3656                 temp2 = temp1 + width * height * 4;
3657                 // use either a custom palette or the quake palette
3658                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3659                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3660                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3661                 Mem_Free(temp1);
3662         }
3663
3664         if (skinframe->qgenerateglow)
3665         {
3666                 skinframe->qgenerateglow = false;
3667                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3668         }
3669
3670         if (colormapped)
3671         {
3672                 skinframe->qgeneratebase = false;
3673                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3674                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3675                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3676         }
3677         else
3678         {
3679                 skinframe->qgeneratemerged = false;
3680                 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);
3681         }
3682
3683         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3684         {
3685                 Mem_Free(skinframe->qpixels);
3686                 skinframe->qpixels = NULL;
3687         }
3688 }
3689
3690 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)
3691 {
3692         int i;
3693         skinframe_t *skinframe;
3694         char vabuf[1024];
3695
3696         if (cls.state == ca_dedicated)
3697                 return NULL;
3698
3699         // if already loaded just return it, otherwise make a new skinframe
3700         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3701         if (skinframe && skinframe->base)
3702                 return skinframe;
3703         textureflags &= ~TEXF_FORCE_RELOAD;
3704
3705         skinframe->stain = NULL;
3706         skinframe->merged = NULL;
3707         skinframe->base = NULL;
3708         skinframe->pants = NULL;
3709         skinframe->shirt = NULL;
3710         skinframe->nmap = NULL;
3711         skinframe->gloss = NULL;
3712         skinframe->glow = NULL;
3713         skinframe->fog = NULL;
3714         skinframe->reflect = NULL;
3715         skinframe->hasalpha = false;
3716
3717         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3718         if (!skindata)
3719                 return NULL;
3720
3721         if (developer_loading.integer)
3722                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3723
3724         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3725         if (textureflags & TEXF_ALPHA)
3726         {
3727                 for (i = 0;i < width * height;i++)
3728                 {
3729                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3730                         {
3731                                 skinframe->hasalpha = true;
3732                                 break;
3733                         }
3734                 }
3735                 if (r_loadfog && skinframe->hasalpha)
3736                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3737         }
3738
3739         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3740         //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]);
3741
3742         return skinframe;
3743 }
3744
3745 skinframe_t *R_SkinFrame_LoadMissing(void)
3746 {
3747         skinframe_t *skinframe;
3748
3749         if (cls.state == ca_dedicated)
3750                 return NULL;
3751
3752         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3753         skinframe->stain = NULL;
3754         skinframe->merged = NULL;
3755         skinframe->base = NULL;
3756         skinframe->pants = NULL;
3757         skinframe->shirt = NULL;
3758         skinframe->nmap = NULL;
3759         skinframe->gloss = NULL;
3760         skinframe->glow = NULL;
3761         skinframe->fog = NULL;
3762         skinframe->reflect = NULL;
3763         skinframe->hasalpha = false;
3764
3765         skinframe->avgcolor[0] = rand() / RAND_MAX;
3766         skinframe->avgcolor[1] = rand() / RAND_MAX;
3767         skinframe->avgcolor[2] = rand() / RAND_MAX;
3768         skinframe->avgcolor[3] = 1;
3769
3770         return skinframe;
3771 }
3772
3773 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3774 typedef struct suffixinfo_s
3775 {
3776         const char *suffix;
3777         qboolean flipx, flipy, flipdiagonal;
3778 }
3779 suffixinfo_t;
3780 static suffixinfo_t suffix[3][6] =
3781 {
3782         {
3783                 {"px",   false, false, false},
3784                 {"nx",   false, false, false},
3785                 {"py",   false, false, false},
3786                 {"ny",   false, false, false},
3787                 {"pz",   false, false, false},
3788                 {"nz",   false, false, false}
3789         },
3790         {
3791                 {"posx", false, false, false},
3792                 {"negx", false, false, false},
3793                 {"posy", false, false, false},
3794                 {"negy", false, false, false},
3795                 {"posz", false, false, false},
3796                 {"negz", false, false, false}
3797         },
3798         {
3799                 {"rt",    true, false,  true},
3800                 {"lf",   false,  true,  true},
3801                 {"ft",    true,  true, false},
3802                 {"bk",   false, false, false},
3803                 {"up",    true, false,  true},
3804                 {"dn",    true, false,  true}
3805         }
3806 };
3807
3808 static int componentorder[4] = {0, 1, 2, 3};
3809
3810 static rtexture_t *R_LoadCubemap(const char *basename)
3811 {
3812         int i, j, cubemapsize;
3813         unsigned char *cubemappixels, *image_buffer;
3814         rtexture_t *cubemaptexture;
3815         char name[256];
3816         // must start 0 so the first loadimagepixels has no requested width/height
3817         cubemapsize = 0;
3818         cubemappixels = NULL;
3819         cubemaptexture = NULL;
3820         // keep trying different suffix groups (posx, px, rt) until one loads
3821         for (j = 0;j < 3 && !cubemappixels;j++)
3822         {
3823                 // load the 6 images in the suffix group
3824                 for (i = 0;i < 6;i++)
3825                 {
3826                         // generate an image name based on the base and and suffix
3827                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3828                         // load it
3829                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3830                         {
3831                                 // an image loaded, make sure width and height are equal
3832                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3833                                 {
3834                                         // if this is the first image to load successfully, allocate the cubemap memory
3835                                         if (!cubemappixels && image_width >= 1)
3836                                         {
3837                                                 cubemapsize = image_width;
3838                                                 // note this clears to black, so unavailable sides are black
3839                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3840                                         }
3841                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3842                                         if (cubemappixels)
3843                                                 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);
3844                                 }
3845                                 else
3846                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3847                                 // free the image
3848                                 Mem_Free(image_buffer);
3849                         }
3850                 }
3851         }
3852         // if a cubemap loaded, upload it
3853         if (cubemappixels)
3854         {
3855                 if (developer_loading.integer)
3856                         Con_Printf("loading cubemap \"%s\"\n", basename);
3857
3858                 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);
3859                 Mem_Free(cubemappixels);
3860         }
3861         else
3862         {
3863                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3864                 if (developer_loading.integer)
3865                 {
3866                         Con_Printf("(tried tried images ");
3867                         for (j = 0;j < 3;j++)
3868                                 for (i = 0;i < 6;i++)
3869                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3870                         Con_Print(" and was unable to find any of them).\n");
3871                 }
3872         }
3873         return cubemaptexture;
3874 }
3875
3876 rtexture_t *R_GetCubemap(const char *basename)
3877 {
3878         int i;
3879         for (i = 0;i < r_texture_numcubemaps;i++)
3880                 if (r_texture_cubemaps[i] != NULL)
3881                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3882                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3883         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3884                 return r_texture_whitecube;
3885         r_texture_numcubemaps++;
3886         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3887         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3888         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3889         return r_texture_cubemaps[i]->texture;
3890 }
3891
3892 static void R_Main_FreeViewCache(void)
3893 {
3894         if (r_refdef.viewcache.entityvisible)
3895                 Mem_Free(r_refdef.viewcache.entityvisible);
3896         if (r_refdef.viewcache.world_pvsbits)
3897                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3898         if (r_refdef.viewcache.world_leafvisible)
3899                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3900         if (r_refdef.viewcache.world_surfacevisible)
3901                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3902         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3903 }
3904
3905 static void R_Main_ResizeViewCache(void)
3906 {
3907         int numentities = r_refdef.scene.numentities;
3908         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3909         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3910         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3911         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3912         if (r_refdef.viewcache.maxentities < numentities)
3913         {
3914                 r_refdef.viewcache.maxentities = numentities;
3915                 if (r_refdef.viewcache.entityvisible)
3916                         Mem_Free(r_refdef.viewcache.entityvisible);
3917                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3918         }
3919         if (r_refdef.viewcache.world_numclusters != numclusters)
3920         {
3921                 r_refdef.viewcache.world_numclusters = numclusters;
3922                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3923                 if (r_refdef.viewcache.world_pvsbits)
3924                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3925                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3926         }
3927         if (r_refdef.viewcache.world_numleafs != numleafs)
3928         {
3929                 r_refdef.viewcache.world_numleafs = numleafs;
3930                 if (r_refdef.viewcache.world_leafvisible)
3931                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3932                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3933         }
3934         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3935         {
3936                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3937                 if (r_refdef.viewcache.world_surfacevisible)
3938                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3939                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3940         }
3941 }
3942
3943 extern rtexture_t *loadingscreentexture;
3944 static void gl_main_start(void)
3945 {
3946         loadingscreentexture = NULL;
3947         r_texture_blanknormalmap = NULL;
3948         r_texture_white = NULL;
3949         r_texture_grey128 = NULL;
3950         r_texture_black = NULL;
3951         r_texture_whitecube = NULL;
3952         r_texture_normalizationcube = NULL;
3953         r_texture_fogattenuation = NULL;
3954         r_texture_fogheighttexture = NULL;
3955         r_texture_gammaramps = NULL;
3956         r_texture_numcubemaps = 0;
3957
3958         r_loaddds = r_texture_dds_load.integer != 0;
3959         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3960
3961         switch(vid.renderpath)
3962         {
3963         case RENDERPATH_GL20:
3964         case RENDERPATH_D3D9:
3965         case RENDERPATH_D3D10:
3966         case RENDERPATH_D3D11:
3967         case RENDERPATH_SOFT:
3968         case RENDERPATH_GLES2:
3969                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3970                 Cvar_SetValueQuick(&gl_combine, 1);
3971                 Cvar_SetValueQuick(&r_glsl, 1);
3972                 r_loadnormalmap = true;
3973                 r_loadgloss = true;
3974                 r_loadfog = false;
3975                 break;
3976         case RENDERPATH_GL13:
3977         case RENDERPATH_GLES1:
3978                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3979                 Cvar_SetValueQuick(&gl_combine, 1);
3980                 Cvar_SetValueQuick(&r_glsl, 0);
3981                 r_loadnormalmap = false;
3982                 r_loadgloss = false;
3983                 r_loadfog = true;
3984                 break;
3985         case RENDERPATH_GL11:
3986                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3987                 Cvar_SetValueQuick(&gl_combine, 0);
3988                 Cvar_SetValueQuick(&r_glsl, 0);
3989                 r_loadnormalmap = false;
3990                 r_loadgloss = false;
3991                 r_loadfog = true;
3992                 break;
3993         }
3994
3995         R_AnimCache_Free();
3996         R_FrameData_Reset();
3997
3998         r_numqueries = 0;
3999         r_maxqueries = 0;
4000         memset(r_queries, 0, sizeof(r_queries));
4001
4002         r_qwskincache = NULL;
4003         r_qwskincache_size = 0;
4004
4005         // due to caching of texture_t references, the collision cache must be reset
4006         Collision_Cache_Reset(true);
4007
4008         // set up r_skinframe loading system for textures
4009         memset(&r_skinframe, 0, sizeof(r_skinframe));
4010         r_skinframe.loadsequence = 1;
4011         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4012
4013         r_main_texturepool = R_AllocTexturePool();
4014         R_BuildBlankTextures();
4015         R_BuildNoTexture();
4016         if (vid.support.arb_texture_cube_map)
4017         {
4018                 R_BuildWhiteCube();
4019                 R_BuildNormalizationCube();
4020         }
4021         r_texture_fogattenuation = NULL;
4022         r_texture_fogheighttexture = NULL;
4023         r_texture_gammaramps = NULL;
4024         //r_texture_fogintensity = NULL;
4025         memset(&r_fb, 0, sizeof(r_fb));
4026         r_glsl_permutation = NULL;
4027         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4028         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4029         glslshaderstring = NULL;
4030 #ifdef SUPPORTD3D
4031         r_hlsl_permutation = NULL;
4032         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4033         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4034 #endif
4035         hlslshaderstring = NULL;
4036         memset(&r_svbsp, 0, sizeof (r_svbsp));
4037
4038         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4039         r_texture_numcubemaps = 0;
4040
4041         r_refdef.fogmasktable_density = 0;
4042 }
4043
4044 static void gl_main_shutdown(void)
4045 {
4046         R_AnimCache_Free();
4047         R_FrameData_Reset();
4048
4049         R_Main_FreeViewCache();
4050
4051         switch(vid.renderpath)
4052         {
4053         case RENDERPATH_GL11:
4054         case RENDERPATH_GL13:
4055         case RENDERPATH_GL20:
4056         case RENDERPATH_GLES1:
4057         case RENDERPATH_GLES2:
4058 #ifdef GL_SAMPLES_PASSED_ARB
4059                 if (r_maxqueries)
4060                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4061 #endif
4062                 break;
4063         case RENDERPATH_D3D9:
4064                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4065                 break;
4066         case RENDERPATH_D3D10:
4067                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4068                 break;
4069         case RENDERPATH_D3D11:
4070                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4071                 break;
4072         case RENDERPATH_SOFT:
4073                 break;
4074         }
4075
4076         r_numqueries = 0;
4077         r_maxqueries = 0;
4078         memset(r_queries, 0, sizeof(r_queries));
4079
4080         r_qwskincache = NULL;
4081         r_qwskincache_size = 0;
4082
4083         // clear out the r_skinframe state
4084         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4085         memset(&r_skinframe, 0, sizeof(r_skinframe));
4086
4087         if (r_svbsp.nodes)
4088                 Mem_Free(r_svbsp.nodes);
4089         memset(&r_svbsp, 0, sizeof (r_svbsp));
4090         R_FreeTexturePool(&r_main_texturepool);
4091         loadingscreentexture = NULL;
4092         r_texture_blanknormalmap = NULL;
4093         r_texture_white = NULL;
4094         r_texture_grey128 = NULL;
4095         r_texture_black = NULL;
4096         r_texture_whitecube = NULL;
4097         r_texture_normalizationcube = NULL;
4098         r_texture_fogattenuation = NULL;
4099         r_texture_fogheighttexture = NULL;
4100         r_texture_gammaramps = NULL;
4101         r_texture_numcubemaps = 0;
4102         //r_texture_fogintensity = NULL;
4103         memset(&r_fb, 0, sizeof(r_fb));
4104         R_GLSL_Restart_f();
4105
4106         r_glsl_permutation = NULL;
4107         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4108         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4109         glslshaderstring = NULL;
4110 #ifdef SUPPORTD3D
4111         r_hlsl_permutation = NULL;
4112         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4113         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4114 #endif
4115         hlslshaderstring = NULL;
4116 }
4117
4118 static void gl_main_newmap(void)
4119 {
4120         // FIXME: move this code to client
4121         char *entities, entname[MAX_QPATH];
4122         if (r_qwskincache)
4123                 Mem_Free(r_qwskincache);
4124         r_qwskincache = NULL;
4125         r_qwskincache_size = 0;
4126         if (cl.worldmodel)
4127         {
4128                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4129                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4130                 {
4131                         CL_ParseEntityLump(entities);
4132                         Mem_Free(entities);
4133                         return;
4134                 }
4135                 if (cl.worldmodel->brush.entities)
4136                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4137         }
4138         R_Main_FreeViewCache();
4139
4140         R_FrameData_Reset();
4141 }
4142
4143 void GL_Main_Init(void)
4144 {
4145         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4146
4147         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4148         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4149         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4150         if (gamemode == GAME_NEHAHRA)
4151         {
4152                 Cvar_RegisterVariable (&gl_fogenable);
4153                 Cvar_RegisterVariable (&gl_fogdensity);
4154                 Cvar_RegisterVariable (&gl_fogred);
4155                 Cvar_RegisterVariable (&gl_foggreen);
4156                 Cvar_RegisterVariable (&gl_fogblue);
4157                 Cvar_RegisterVariable (&gl_fogstart);
4158                 Cvar_RegisterVariable (&gl_fogend);
4159                 Cvar_RegisterVariable (&gl_skyclip);
4160         }
4161         Cvar_RegisterVariable(&r_motionblur);
4162         Cvar_RegisterVariable(&r_damageblur);
4163         Cvar_RegisterVariable(&r_motionblur_averaging);
4164         Cvar_RegisterVariable(&r_motionblur_randomize);
4165         Cvar_RegisterVariable(&r_motionblur_minblur);
4166         Cvar_RegisterVariable(&r_motionblur_maxblur);
4167         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4168         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4169         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4170         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4171         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4172         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4173         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4174         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4175         Cvar_RegisterVariable(&r_equalize_entities_by);
4176         Cvar_RegisterVariable(&r_equalize_entities_to);
4177         Cvar_RegisterVariable(&r_depthfirst);
4178         Cvar_RegisterVariable(&r_useinfinitefarclip);
4179         Cvar_RegisterVariable(&r_farclip_base);
4180         Cvar_RegisterVariable(&r_farclip_world);
4181         Cvar_RegisterVariable(&r_nearclip);
4182         Cvar_RegisterVariable(&r_deformvertexes);
4183         Cvar_RegisterVariable(&r_transparent);
4184         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4185         Cvar_RegisterVariable(&r_showoverdraw);
4186         Cvar_RegisterVariable(&r_showbboxes);
4187         Cvar_RegisterVariable(&r_showsurfaces);
4188         Cvar_RegisterVariable(&r_showtris);
4189         Cvar_RegisterVariable(&r_shownormals);
4190         Cvar_RegisterVariable(&r_showlighting);
4191         Cvar_RegisterVariable(&r_showshadowvolumes);
4192         Cvar_RegisterVariable(&r_showcollisionbrushes);
4193         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4194         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4195         Cvar_RegisterVariable(&r_showdisabledepthtest);
4196         Cvar_RegisterVariable(&r_drawportals);
4197         Cvar_RegisterVariable(&r_drawentities);
4198         Cvar_RegisterVariable(&r_draw2d);
4199         Cvar_RegisterVariable(&r_drawworld);
4200         Cvar_RegisterVariable(&r_cullentities_trace);
4201         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4202         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4203         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4204         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4205         Cvar_RegisterVariable(&r_sortentities);
4206         Cvar_RegisterVariable(&r_drawviewmodel);
4207         Cvar_RegisterVariable(&r_drawexteriormodel);
4208         Cvar_RegisterVariable(&r_speeds);
4209         Cvar_RegisterVariable(&r_fullbrights);
4210         Cvar_RegisterVariable(&r_wateralpha);
4211         Cvar_RegisterVariable(&r_dynamic);
4212         Cvar_RegisterVariable(&r_fakelight);
4213         Cvar_RegisterVariable(&r_fakelight_intensity);
4214         Cvar_RegisterVariable(&r_fullbright);
4215         Cvar_RegisterVariable(&r_shadows);
4216         Cvar_RegisterVariable(&r_shadows_darken);
4217         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4218         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4219         Cvar_RegisterVariable(&r_shadows_throwdistance);
4220         Cvar_RegisterVariable(&r_shadows_throwdirection);
4221         Cvar_RegisterVariable(&r_shadows_focus);
4222         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4223         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4224         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4225         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4226         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4227         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4228         Cvar_RegisterVariable(&r_fog_exp2);
4229         Cvar_RegisterVariable(&r_fog_clear);
4230         Cvar_RegisterVariable(&r_drawfog);
4231         Cvar_RegisterVariable(&r_transparentdepthmasking);
4232         Cvar_RegisterVariable(&r_transparent_sortmindist);
4233         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4234         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4235         Cvar_RegisterVariable(&r_texture_dds_load);
4236         Cvar_RegisterVariable(&r_texture_dds_save);
4237         Cvar_RegisterVariable(&r_textureunits);
4238         Cvar_RegisterVariable(&gl_combine);
4239         Cvar_RegisterVariable(&r_viewfbo);
4240         Cvar_RegisterVariable(&r_viewscale);
4241         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4242         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4243         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4244         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4245         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4246         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4247         Cvar_RegisterVariable(&r_glsl);
4248         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4249         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4250         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4251         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4252         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4253         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4254         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4255         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4256         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4257         Cvar_RegisterVariable(&r_glsl_postprocess);
4258         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4259         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4260         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4262         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4266
4267         Cvar_RegisterVariable(&r_water);
4268         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4269         Cvar_RegisterVariable(&r_water_clippingplanebias);
4270         Cvar_RegisterVariable(&r_water_refractdistort);
4271         Cvar_RegisterVariable(&r_water_reflectdistort);
4272         Cvar_RegisterVariable(&r_water_scissormode);
4273         Cvar_RegisterVariable(&r_water_lowquality);
4274         Cvar_RegisterVariable(&r_water_hideplayer);
4275         Cvar_RegisterVariable(&r_water_fbo);
4276
4277         Cvar_RegisterVariable(&r_lerpsprites);
4278         Cvar_RegisterVariable(&r_lerpmodels);
4279         Cvar_RegisterVariable(&r_lerplightstyles);
4280         Cvar_RegisterVariable(&r_waterscroll);
4281         Cvar_RegisterVariable(&r_bloom);
4282         Cvar_RegisterVariable(&r_bloom_colorscale);
4283         Cvar_RegisterVariable(&r_bloom_brighten);
4284         Cvar_RegisterVariable(&r_bloom_blur);
4285         Cvar_RegisterVariable(&r_bloom_resolution);
4286         Cvar_RegisterVariable(&r_bloom_colorexponent);
4287         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4288         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4289         Cvar_RegisterVariable(&r_hdr_glowintensity);
4290         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4294         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4295         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4296         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4298         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4299         Cvar_RegisterVariable(&developer_texturelogging);
4300         Cvar_RegisterVariable(&gl_lightmaps);
4301         Cvar_RegisterVariable(&r_test);
4302         Cvar_RegisterVariable(&r_glsl_saturation);
4303         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4304         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4305         Cvar_RegisterVariable(&r_framedatasize);
4306         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4307                 Cvar_SetValue("r_fullbrights", 0);
4308         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4309 }
4310
4311 void Render_Init(void)
4312 {
4313         gl_backend_init();
4314         R_Textures_Init();
4315         GL_Main_Init();
4316         Font_Init();
4317         GL_Draw_Init();
4318         R_Shadow_Init();
4319         R_Sky_Init();
4320         GL_Surf_Init();
4321         Sbar_Init();
4322         R_Particles_Init();
4323         R_Explosion_Init();
4324         R_LightningBeams_Init();
4325         Mod_RenderInit();
4326 }
4327
4328 /*
4329 ===============
4330 GL_Init
4331 ===============
4332 */
4333 #ifndef USE_GLES2
4334 extern char *ENGINE_EXTENSIONS;
4335 void GL_Init (void)
4336 {
4337         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4338         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4339         gl_version = (const char *)qglGetString(GL_VERSION);
4340         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4341
4342         if (!gl_extensions)
4343                 gl_extensions = "";
4344         if (!gl_platformextensions)
4345                 gl_platformextensions = "";
4346
4347         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4348         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4349         Con_Printf("GL_VERSION: %s\n", gl_version);
4350         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4351         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4352
4353         VID_CheckExtensions();
4354
4355         // LordHavoc: report supported extensions
4356         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4357
4358         // clear to black (loading plaque will be seen over this)
4359         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4360 }
4361 #endif
4362
4363 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4364 {
4365         int i;
4366         mplane_t *p;
4367         if (r_trippy.integer)
4368                 return false;
4369         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4370         {
4371                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4372                 if (i == 4)
4373                         continue;
4374                 p = r_refdef.view.frustum + i;
4375                 switch(p->signbits)
4376                 {
4377                 default:
4378                 case 0:
4379                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 1:
4383                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 2:
4387                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 3:
4391                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 4:
4395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 5:
4399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 6:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 7:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 }
4411         }
4412         return false;
4413 }
4414
4415 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4416 {
4417         int i;
4418         const mplane_t *p;
4419         if (r_trippy.integer)
4420                 return false;
4421         for (i = 0;i < numplanes;i++)
4422         {
4423                 p = planes + i;
4424                 switch(p->signbits)
4425                 {
4426                 default:
4427                 case 0:
4428                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 1:
4432                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 2:
4436                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 3:
4440                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 4:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 5:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 6:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 7:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 }
4460         }
4461         return false;
4462 }
4463
4464 //==================================================================================
4465
4466 // LordHavoc: this stores temporary data used within the same frame
4467
4468 typedef struct r_framedata_mem_s
4469 {
4470         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4471         size_t size; // how much usable space
4472         size_t current; // how much space in use
4473         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4474         size_t wantedsize; // how much space was allocated
4475         unsigned char *data; // start of real data (16byte aligned)
4476 }
4477 r_framedata_mem_t;
4478
4479 static r_framedata_mem_t *r_framedata_mem;
4480
4481 void R_FrameData_Reset(void)
4482 {
4483         while (r_framedata_mem)
4484         {
4485                 r_framedata_mem_t *next = r_framedata_mem->purge;
4486                 Mem_Free(r_framedata_mem);
4487                 r_framedata_mem = next;
4488         }
4489 }
4490
4491 static void R_FrameData_Resize(void)
4492 {
4493         size_t wantedsize;
4494         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4495         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4496         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4497         {
4498                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4499                 newmem->wantedsize = wantedsize;
4500                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4501                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4502                 newmem->current = 0;
4503                 newmem->mark = 0;
4504                 newmem->purge = r_framedata_mem;
4505                 r_framedata_mem = newmem;
4506         }
4507 }
4508
4509 void R_FrameData_NewFrame(void)
4510 {
4511         R_FrameData_Resize();
4512         if (!r_framedata_mem)
4513                 return;
4514         // if we ran out of space on the last frame, free the old memory now
4515         while (r_framedata_mem->purge)
4516         {
4517                 // repeatedly remove the second item in the list, leaving only head
4518                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4519                 Mem_Free(r_framedata_mem->purge);
4520                 r_framedata_mem->purge = next;
4521         }
4522         // reset the current mem pointer
4523         r_framedata_mem->current = 0;
4524         r_framedata_mem->mark = 0;
4525 }
4526
4527 void *R_FrameData_Alloc(size_t size)
4528 {
4529         void *data;
4530
4531         // align to 16 byte boundary - the data pointer is already aligned, so we
4532         // only need to ensure the size of every allocation is also aligned
4533         size = (size + 15) & ~15;
4534
4535         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4536         {
4537                 // emergency - we ran out of space, allocate more memory
4538                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4539                 R_FrameData_Resize();
4540         }
4541
4542         data = r_framedata_mem->data + r_framedata_mem->current;
4543         r_framedata_mem->current += size;
4544
4545         // count the usage for stats
4546         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4547         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4548
4549         return (void *)data;
4550 }
4551
4552 void *R_FrameData_Store(size_t size, void *data)
4553 {
4554         void *d = R_FrameData_Alloc(size);
4555         if (d && data)
4556                 memcpy(d, data, size);
4557         return d;
4558 }
4559
4560 void R_FrameData_SetMark(void)
4561 {
4562         if (!r_framedata_mem)
4563                 return;
4564         r_framedata_mem->mark = r_framedata_mem->current;
4565 }
4566
4567 void R_FrameData_ReturnToMark(void)
4568 {
4569         if (!r_framedata_mem)
4570                 return;
4571         r_framedata_mem->current = r_framedata_mem->mark;
4572 }
4573
4574 //==================================================================================
4575
4576 // LordHavoc: animcache originally written by Echon, rewritten since then
4577
4578 /**
4579  * Animation cache prevents re-generating mesh data for an animated model
4580  * multiple times in one frame for lighting, shadowing, reflections, etc.
4581  */
4582
4583 void R_AnimCache_Free(void)
4584 {
4585 }
4586
4587 void R_AnimCache_ClearCache(void)
4588 {
4589         int i;
4590         entity_render_t *ent;
4591
4592         for (i = 0;i < r_refdef.scene.numentities;i++)
4593         {
4594                 ent = r_refdef.scene.entities[i];
4595                 ent->animcache_vertex3f = NULL;
4596                 ent->animcache_normal3f = NULL;
4597                 ent->animcache_svector3f = NULL;
4598                 ent->animcache_tvector3f = NULL;
4599                 ent->animcache_vertexmesh = NULL;
4600                 ent->animcache_vertex3fbuffer = NULL;
4601                 ent->animcache_vertexmeshbuffer = NULL;
4602         }
4603 }
4604
4605 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4606 {
4607         int i;
4608
4609         // check if we need the meshbuffers
4610         if (!vid.useinterleavedarrays)
4611                 return;
4612
4613         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4614                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4615         // TODO: upload vertex3f buffer?
4616         if (ent->animcache_vertexmesh)
4617         {
4618                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4619                 for (i = 0;i < numvertices;i++)
4620                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4621                 if (ent->animcache_svector3f)
4622                         for (i = 0;i < numvertices;i++)
4623                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4624                 if (ent->animcache_tvector3f)
4625                         for (i = 0;i < numvertices;i++)
4626                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4627                 if (ent->animcache_normal3f)
4628                         for (i = 0;i < numvertices;i++)
4629                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4630                 // TODO: upload vertexmeshbuffer?
4631         }
4632 }
4633
4634 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4635 {
4636         dp_model_t *model = ent->model;
4637         int numvertices;
4638         // see if it's already cached this frame
4639         if (ent->animcache_vertex3f)
4640         {
4641                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4642                 if (wantnormals || wanttangents)
4643                 {
4644                         if (ent->animcache_normal3f)
4645                                 wantnormals = false;
4646                         if (ent->animcache_svector3f)
4647                                 wanttangents = false;
4648                         if (wantnormals || wanttangents)
4649                         {
4650                                 numvertices = model->surfmesh.num_vertices;
4651                                 if (wantnormals)
4652                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                                 if (wanttangents)
4654                                 {
4655                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4656                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4657                                 }
4658                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4659                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4660                         }
4661                 }
4662         }
4663         else
4664         {
4665                 // see if this ent is worth caching
4666                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4667                         return false;
4668                 // get some memory for this entity and generate mesh data
4669                 numvertices = model->surfmesh.num_vertices;
4670                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671                 if (wantnormals)
4672                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                 if (wanttangents)
4674                 {
4675                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4676                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4677                 }
4678                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4679                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4680         }
4681         return true;
4682 }
4683
4684 void R_AnimCache_CacheVisibleEntities(void)
4685 {
4686         int i;
4687         qboolean wantnormals = true;
4688         qboolean wanttangents = !r_showsurfaces.integer;
4689
4690         switch(vid.renderpath)
4691         {
4692         case RENDERPATH_GL20:
4693         case RENDERPATH_D3D9:
4694         case RENDERPATH_D3D10:
4695         case RENDERPATH_D3D11:
4696         case RENDERPATH_GLES2:
4697                 break;
4698         case RENDERPATH_GL11:
4699         case RENDERPATH_GL13:
4700         case RENDERPATH_GLES1:
4701                 wanttangents = false;
4702                 break;
4703         case RENDERPATH_SOFT:
4704                 break;
4705         }
4706
4707         if (r_shownormals.integer)
4708                 wanttangents = wantnormals = true;
4709
4710         // TODO: thread this
4711         // NOTE: R_PrepareRTLights() also caches entities
4712
4713         for (i = 0;i < r_refdef.scene.numentities;i++)
4714                 if (r_refdef.viewcache.entityvisible[i])
4715                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4716 }
4717
4718 //==================================================================================
4719
4720 extern cvar_t r_overheadsprites_pushback;
4721
4722 static void R_View_UpdateEntityLighting (void)
4723 {
4724         int i;
4725         entity_render_t *ent;
4726         vec3_t tempdiffusenormal, avg;
4727         vec_t f, fa, fd, fdd;
4728         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4729
4730         for (i = 0;i < r_refdef.scene.numentities;i++)
4731         {
4732                 ent = r_refdef.scene.entities[i];
4733
4734                 // skip unseen models and models that updated by CSQC
4735                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4736                         continue;
4737
4738                 // skip bsp models
4739                 if (ent->model && ent->model->brush.num_leafs)
4740                 {
4741                         // TODO: use modellight for r_ambient settings on world?
4742                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4743                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4744                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4745                         continue;
4746                 }
4747
4748                 // fetch the lighting from the worldmodel data
4749                 VectorClear(ent->modellight_ambient);
4750                 VectorClear(ent->modellight_diffuse);
4751                 VectorClear(tempdiffusenormal);
4752                 if (ent->flags & RENDER_LIGHT)
4753                 {
4754                         vec3_t org;
4755                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4756
4757                         // complete lightning for lit sprites
4758                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4759                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4760                         {
4761                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4762                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4763                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4764                         }
4765                         else
4766                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4767
4768                         if(ent->flags & RENDER_EQUALIZE)
4769                         {
4770                                 // first fix up ambient lighting...
4771                                 if(r_equalize_entities_minambient.value > 0)
4772                                 {
4773                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4774                                         if(fd > 0)
4775                                         {
4776                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4777                                                 if(fa < r_equalize_entities_minambient.value * fd)
4778                                                 {
4779                                                         // solve:
4780                                                         //   fa'/fd' = minambient
4781                                                         //   fa'+0.25*fd' = fa+0.25*fd
4782                                                         //   ...
4783                                                         //   fa' = fd' * minambient
4784                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4785                                                         //   ...
4786                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4787                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4788                                                         //   ...
4789                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4790                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4791                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4792                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4793                                                 }
4794                                         }
4795                                 }
4796
4797                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4798                                 {
4799                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4800                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4801                                         f = fa + 0.25 * fd;
4802                                         if(f > 0)
4803                                         {
4804                                                 // adjust brightness and saturation to target
4805                                                 avg[0] = avg[1] = avg[2] = fa / f;
4806                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4807                                                 avg[0] = avg[1] = avg[2] = fd / f;
4808                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4809                                         }
4810                                 }
4811                         }
4812                 }
4813                 else // highly rare
4814                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4815
4816                 // move the light direction into modelspace coordinates for lighting code
4817                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4818                 if(VectorLength2(ent->modellight_lightdir) == 0)
4819                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4820                 VectorNormalize(ent->modellight_lightdir);
4821         }
4822 }
4823
4824 #define MAX_LINEOFSIGHTTRACES 64
4825
4826 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4827 {
4828         int i;
4829         vec3_t boxmins, boxmaxs;
4830         vec3_t start;
4831         vec3_t end;
4832         dp_model_t *model = r_refdef.scene.worldmodel;
4833
4834         if (!model || !model->brush.TraceLineOfSight)
4835                 return true;
4836
4837         // expand the box a little
4838         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4839         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4840         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4841         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4842         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4843         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4844
4845         // return true if eye is inside enlarged box
4846         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4847                 return true;
4848
4849         // try center
4850         VectorCopy(eye, start);
4851         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4852         if (model->brush.TraceLineOfSight(model, start, end))
4853                 return true;
4854
4855         // try various random positions
4856         for (i = 0;i < numsamples;i++)
4857         {
4858                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4859                 if (model->brush.TraceLineOfSight(model, start, end))
4860                         return true;
4861         }
4862
4863         return false;
4864 }
4865
4866
4867 static void R_View_UpdateEntityVisible (void)
4868 {
4869         int i;
4870         int renderimask;
4871         int samples;
4872         entity_render_t *ent;
4873
4874         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4875                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4876                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4877                 :                                                          RENDER_EXTERIORMODEL;
4878         if (!r_drawviewmodel.integer)
4879                 renderimask |= RENDER_VIEWMODEL;
4880         if (!r_drawexteriormodel.integer)
4881                 renderimask |= RENDER_EXTERIORMODEL;
4882         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4883         {
4884                 // worldmodel can check visibility
4885                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4886                 for (i = 0;i < r_refdef.scene.numentities;i++)
4887                 {
4888                         ent = r_refdef.scene.entities[i];
4889                         if (!(ent->flags & renderimask))
4890                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4891                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4892                                 r_refdef.viewcache.entityvisible[i] = true;
4893                 }
4894         }
4895         else
4896         {
4897                 // no worldmodel or it can't check visibility
4898                 for (i = 0;i < r_refdef.scene.numentities;i++)
4899                 {
4900                         ent = r_refdef.scene.entities[i];
4901                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4902                 }
4903         }
4904         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4905                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4906         {
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         if (!r_refdef.viewcache.entityvisible[i])
4910                                 continue;
4911                         ent = r_refdef.scene.entities[i];
4912                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4913                         {
4914                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4915                                 if (samples < 0)
4916                                         continue; // temp entities do pvs only
4917                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4918                                         ent->last_trace_visibility = realtime;
4919                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4920                                         r_refdef.viewcache.entityvisible[i] = 0;
4921                         }
4922                 }
4923         }
4924 }
4925
4926 /// only used if skyrendermasked, and normally returns false
4927 static int R_DrawBrushModelsSky (void)
4928 {
4929         int i, sky;
4930         entity_render_t *ent;
4931
4932         sky = false;
4933         for (i = 0;i < r_refdef.scene.numentities;i++)
4934         {
4935                 if (!r_refdef.viewcache.entityvisible[i])
4936                         continue;
4937                 ent = r_refdef.scene.entities[i];
4938                 if (!ent->model || !ent->model->DrawSky)
4939                         continue;
4940                 ent->model->DrawSky(ent);
4941                 sky = true;
4942         }
4943         return sky;
4944 }
4945
4946 static void R_DrawNoModel(entity_render_t *ent);
4947 static void R_DrawModels(void)
4948 {
4949         int i;
4950         entity_render_t *ent;
4951
4952         for (i = 0;i < r_refdef.scene.numentities;i++)
4953         {
4954                 if (!r_refdef.viewcache.entityvisible[i])
4955                         continue;
4956                 ent = r_refdef.scene.entities[i];
4957                 r_refdef.stats.entities++;
4958                 /*
4959                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4960                 {
4961                         vec3_t f, l, u, o;
4962                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4963                         Con_Printf("R_DrawModels\n");
4964                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4965                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4966                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4967                 }
4968                 */
4969                 if (ent->model && ent->model->Draw != NULL)
4970                         ent->model->Draw(ent);
4971                 else
4972                         R_DrawNoModel(ent);
4973         }
4974 }
4975
4976 static void R_DrawModelsDepth(void)
4977 {
4978         int i;
4979         entity_render_t *ent;
4980
4981         for (i = 0;i < r_refdef.scene.numentities;i++)
4982         {
4983                 if (!r_refdef.viewcache.entityvisible[i])
4984                         continue;
4985                 ent = r_refdef.scene.entities[i];
4986                 if (ent->model && ent->model->DrawDepth != NULL)
4987                         ent->model->DrawDepth(ent);
4988         }
4989 }
4990
4991 static void R_DrawModelsDebug(void)
4992 {
4993         int i;
4994         entity_render_t *ent;
4995
4996         for (i = 0;i < r_refdef.scene.numentities;i++)
4997         {
4998                 if (!r_refdef.viewcache.entityvisible[i])
4999                         continue;
5000                 ent = r_refdef.scene.entities[i];
5001                 if (ent->model && ent->model->DrawDebug != NULL)
5002                         ent->model->DrawDebug(ent);
5003         }
5004 }
5005
5006 static void R_DrawModelsAddWaterPlanes(void)
5007 {
5008         int i;
5009         entity_render_t *ent;
5010
5011         for (i = 0;i < r_refdef.scene.numentities;i++)
5012         {
5013                 if (!r_refdef.viewcache.entityvisible[i])
5014                         continue;
5015                 ent = r_refdef.scene.entities[i];
5016                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5017                         ent->model->DrawAddWaterPlanes(ent);
5018         }
5019 }
5020
5021 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5022
5023 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5024 {
5025         if (r_hdr_irisadaptation.integer)
5026         {
5027                 vec3_t p;
5028                 vec3_t ambient;
5029                 vec3_t diffuse;
5030                 vec3_t diffusenormal;
5031                 vec3_t forward;
5032                 vec_t brightness = 0.0f;
5033                 vec_t goal;
5034                 vec_t current;
5035                 vec_t d;
5036                 int c;
5037                 VectorCopy(r_refdef.view.forward, forward);
5038                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5039                 {
5040                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5041                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5042                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5043                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5044                         d = DotProduct(forward, diffusenormal);
5045                         brightness += VectorLength(ambient);
5046                         if (d > 0)
5047                                 brightness += d * VectorLength(diffuse);
5048                 }
5049                 brightness *= 1.0f / c;
5050                 brightness += 0.00001f; // make sure it's never zero
5051                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5052                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5053                 current = r_hdr_irisadaptation_value.value;
5054                 if (current < goal)
5055                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5056                 else if (current > goal)
5057                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5058                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5059                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5060         }
5061         else if (r_hdr_irisadaptation_value.value != 1.0f)
5062                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5063 }
5064
5065 static void R_View_SetFrustum(const int *scissor)
5066 {
5067         int i;
5068         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5069         vec3_t forward, left, up, origin, v;
5070
5071         if(scissor)
5072         {
5073                 // flipped x coordinates (because x points left here)
5074                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5075                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5076
5077                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5078                 switch(vid.renderpath)
5079                 {
5080                         case RENDERPATH_D3D9:
5081                         case RENDERPATH_D3D10:
5082                         case RENDERPATH_D3D11:
5083                                 // non-flipped y coordinates
5084                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5085                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5086                                 break;
5087                         case RENDERPATH_SOFT:
5088                         case RENDERPATH_GL11:
5089                         case RENDERPATH_GL13:
5090                         case RENDERPATH_GL20:
5091                         case RENDERPATH_GLES1:
5092                         case RENDERPATH_GLES2:
5093                                 // non-flipped y coordinates
5094                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5095                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5096                                 break;
5097                 }
5098         }
5099
5100         // we can't trust r_refdef.view.forward and friends in reflected scenes
5101         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5102
5103 #if 0
5104         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5105         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5106         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5107         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5108         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5109         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5110         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5111         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5112         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5113         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5114         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5115         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5116 #endif
5117
5118 #if 0
5119         zNear = r_refdef.nearclip;
5120         nudge = 1.0 - 1.0 / (1<<23);
5121         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5122         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5123         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5124         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5125         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5126         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5127         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5128         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5129 #endif
5130
5131
5132
5133 #if 0
5134         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5135         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5136         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5137         r_refdef.view.frustum[0].dist = m[15] - m[12];
5138
5139         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5140         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5141         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5142         r_refdef.view.frustum[1].dist = m[15] + m[12];
5143
5144         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5145         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5146         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5147         r_refdef.view.frustum[2].dist = m[15] - m[13];
5148
5149         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5150         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5151         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5152         r_refdef.view.frustum[3].dist = m[15] + m[13];
5153
5154         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5155         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5156         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5157         r_refdef.view.frustum[4].dist = m[15] - m[14];
5158
5159         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5160         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5161         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5162         r_refdef.view.frustum[5].dist = m[15] + m[14];
5163 #endif
5164
5165         if (r_refdef.view.useperspective)
5166         {
5167                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5168                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5169                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5170                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5171                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5172
5173                 // then the normals from the corners relative to origin
5174                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5175                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5176                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5177                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5178
5179                 // in a NORMAL view, forward cross left == up
5180                 // in a REFLECTED view, forward cross left == down
5181                 // so our cross products above need to be adjusted for a left handed coordinate system
5182                 CrossProduct(forward, left, v);
5183                 if(DotProduct(v, up) < 0)
5184                 {
5185                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5186                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5187                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5188                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5189                 }
5190
5191                 // Leaving those out was a mistake, those were in the old code, and they
5192                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5193                 // I couldn't reproduce it after adding those normalizations. --blub
5194                 VectorNormalize(r_refdef.view.frustum[0].normal);
5195                 VectorNormalize(r_refdef.view.frustum[1].normal);
5196                 VectorNormalize(r_refdef.view.frustum[2].normal);
5197                 VectorNormalize(r_refdef.view.frustum[3].normal);
5198
5199                 // make the corners absolute
5200                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5201                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5202                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5203                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5204
5205                 // one more normal
5206                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5207
5208                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5209                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5210                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5211                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5212                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5213         }
5214         else
5215         {
5216                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5217                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5218                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5219                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5220                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5221                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5222                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5223                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5224                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5225                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5226         }
5227         r_refdef.view.numfrustumplanes = 5;
5228
5229         if (r_refdef.view.useclipplane)
5230         {
5231                 r_refdef.view.numfrustumplanes = 6;
5232                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5233         }
5234
5235         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5236                 PlaneClassify(r_refdef.view.frustum + i);
5237
5238         // LordHavoc: note to all quake engine coders, Quake had a special case
5239         // for 90 degrees which assumed a square view (wrong), so I removed it,
5240         // Quake2 has it disabled as well.
5241
5242         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5243         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5244         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5245         //PlaneClassify(&frustum[0]);
5246
5247         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5248         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5249         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5250         //PlaneClassify(&frustum[1]);
5251
5252         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5253         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5254         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5255         //PlaneClassify(&frustum[2]);
5256
5257         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5258         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5259         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5260         //PlaneClassify(&frustum[3]);
5261
5262         // nearclip plane
5263         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5264         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5265         //PlaneClassify(&frustum[4]);
5266 }
5267
5268 static void R_View_UpdateWithScissor(const int *myscissor)
5269 {
5270         R_Main_ResizeViewCache();
5271         R_View_SetFrustum(myscissor);
5272         R_View_WorldVisibility(r_refdef.view.useclipplane);
5273         R_View_UpdateEntityVisible();
5274         R_View_UpdateEntityLighting();
5275         R_AnimCache_CacheVisibleEntities();
5276 }
5277
5278 static void R_View_Update(void)
5279 {
5280         R_Main_ResizeViewCache();
5281         R_View_SetFrustum(NULL);
5282         R_View_WorldVisibility(r_refdef.view.useclipplane);
5283         R_View_UpdateEntityVisible();
5284         R_View_UpdateEntityLighting();
5285         R_AnimCache_CacheVisibleEntities();
5286 }
5287
5288 float viewscalefpsadjusted = 1.0f;
5289
5290 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5291 {
5292         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5293         scale = bound(0.03125f, scale, 1.0f);
5294         *outwidth = (int)ceil(width * scale);
5295         *outheight = (int)ceil(height * scale);
5296 }
5297
5298 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5299 {
5300         const float *customclipplane = NULL;
5301         float plane[4];
5302         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5303         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5304         {
5305                 // LordHavoc: couldn't figure out how to make this approach the
5306                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5307                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5308                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5309                         dist = r_refdef.view.clipplane.dist;
5310                 plane[0] = r_refdef.view.clipplane.normal[0];
5311                 plane[1] = r_refdef.view.clipplane.normal[1];
5312                 plane[2] = r_refdef.view.clipplane.normal[2];
5313                 plane[3] = -dist;
5314                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5315         }
5316
5317         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5318         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5319
5320         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5321         if (!r_refdef.view.useperspective)
5322                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5323         else if (vid.stencil && r_useinfinitefarclip.integer)
5324                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5325         else
5326                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5327         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5328         R_SetViewport(&r_refdef.view.viewport);
5329         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5330         {
5331                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5332                 float screenplane[4];
5333                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5334                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5335                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5336                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5337                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5338         }
5339 }
5340
5341 void R_EntityMatrix(const matrix4x4_t *matrix)
5342 {
5343         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5344         {
5345                 gl_modelmatrixchanged = false;
5346                 gl_modelmatrix = *matrix;
5347                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5348                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5349                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5350                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5351                 CHECKGLERROR
5352                 switch(vid.renderpath)
5353                 {
5354                 case RENDERPATH_D3D9:
5355 #ifdef SUPPORTD3D
5356                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5357                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5358 #endif
5359                         break;
5360                 case RENDERPATH_D3D10:
5361                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5362                         break;
5363                 case RENDERPATH_D3D11:
5364                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5365                         break;
5366                 case RENDERPATH_GL11:
5367                 case RENDERPATH_GL13:
5368                 case RENDERPATH_GLES1:
5369                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5370                         break;
5371                 case RENDERPATH_SOFT:
5372                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5373                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5374                         break;
5375                 case RENDERPATH_GL20:
5376                 case RENDERPATH_GLES2:
5377                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5378                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5379                         break;
5380                 }
5381         }
5382 }
5383
5384 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5385 {
5386         r_viewport_t viewport;
5387         DrawQ_Finish();
5388
5389         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5390         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);
5391         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5392         R_SetViewport(&viewport);
5393         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5394         GL_Color(1, 1, 1, 1);
5395         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5396         GL_BlendFunc(GL_ONE, GL_ZERO);
5397         GL_ScissorTest(false);
5398         GL_DepthMask(false);
5399         GL_DepthRange(0, 1);
5400         GL_DepthTest(false);
5401         GL_DepthFunc(GL_LEQUAL);
5402         R_EntityMatrix(&identitymatrix);
5403         R_Mesh_ResetTextureState();
5404         GL_PolygonOffset(0, 0);
5405         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5406         switch(vid.renderpath)
5407         {
5408         case RENDERPATH_GL11:
5409         case RENDERPATH_GL13:
5410         case RENDERPATH_GL20:
5411         case RENDERPATH_GLES1:
5412         case RENDERPATH_GLES2:
5413                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5414                 break;
5415         case RENDERPATH_D3D9:
5416         case RENDERPATH_D3D10:
5417         case RENDERPATH_D3D11:
5418         case RENDERPATH_SOFT:
5419                 break;
5420         }
5421         GL_CullFace(GL_NONE);
5422 }
5423
5424 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5425 {
5426         DrawQ_Finish();
5427
5428         R_SetupView(true, fbo, depthtexture, colortexture);
5429         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5430         GL_Color(1, 1, 1, 1);
5431         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5432         GL_BlendFunc(GL_ONE, GL_ZERO);
5433         GL_ScissorTest(true);
5434         GL_DepthMask(true);
5435         GL_DepthRange(0, 1);
5436         GL_DepthTest(true);
5437         GL_DepthFunc(GL_LEQUAL);
5438         R_EntityMatrix(&identitymatrix);
5439         R_Mesh_ResetTextureState();
5440         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5441         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5442         switch(vid.renderpath)
5443         {
5444         case RENDERPATH_GL11:
5445         case RENDERPATH_GL13:
5446         case RENDERPATH_GL20:
5447         case RENDERPATH_GLES1:
5448         case RENDERPATH_GLES2:
5449                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5450                 break;
5451         case RENDERPATH_D3D9:
5452         case RENDERPATH_D3D10:
5453         case RENDERPATH_D3D11:
5454         case RENDERPATH_SOFT:
5455                 break;
5456         }
5457         GL_CullFace(r_refdef.view.cullface_back);
5458 }
5459
5460 /*
5461 ================
5462 R_RenderView_UpdateViewVectors
5463 ================
5464 */
5465 static void R_RenderView_UpdateViewVectors(void)
5466 {
5467         // break apart the view matrix into vectors for various purposes
5468         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5469         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5470         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5471         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5472         // make an inverted copy of the view matrix for tracking sprites
5473         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5474 }
5475
5476 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5477 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5478
5479 static void R_Water_StartFrame(void)
5480 {
5481         int i;
5482         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5483         r_waterstate_waterplane_t *p;
5484         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5485
5486         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5487                 return;
5488
5489         switch(vid.renderpath)
5490         {
5491         case RENDERPATH_GL20:
5492         case RENDERPATH_D3D9:
5493         case RENDERPATH_D3D10:
5494         case RENDERPATH_D3D11:
5495         case RENDERPATH_SOFT:
5496         case RENDERPATH_GLES2:
5497                 break;
5498         case RENDERPATH_GL11:
5499         case RENDERPATH_GL13:
5500         case RENDERPATH_GLES1:
5501                 return;
5502         }
5503
5504         // set waterwidth and waterheight to the water resolution that will be
5505         // used (often less than the screen resolution for faster rendering)
5506         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5507
5508         // calculate desired texture sizes
5509         // can't use water if the card does not support the texture size
5510         if (!r_water.integer || r_showsurfaces.integer)
5511                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5512         else if (vid.support.arb_texture_non_power_of_two)
5513         {
5514                 texturewidth = waterwidth;
5515                 textureheight = waterheight;
5516                 camerawidth = waterwidth;
5517                 cameraheight = waterheight;
5518         }
5519         else
5520         {
5521                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5522                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5523                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5524                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5525         }
5526
5527         // allocate textures as needed
5528         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5529         {
5530                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5531                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5532                 {
5533                         if (p->texture_refraction)
5534                                 R_FreeTexture(p->texture_refraction);
5535                         p->texture_refraction = NULL;
5536                         if (p->fbo_refraction)
5537                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5538                         p->fbo_refraction = 0;
5539                         if (p->texture_reflection)
5540                                 R_FreeTexture(p->texture_reflection);
5541                         p->texture_reflection = NULL;
5542                         if (p->fbo_reflection)
5543                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5544                         p->fbo_reflection = 0;
5545                         if (p->texture_camera)
5546                                 R_FreeTexture(p->texture_camera);
5547                         p->texture_camera = NULL;
5548                         if (p->fbo_camera)
5549                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5550                         p->fbo_camera = 0;
5551                 }
5552                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5553                 r_fb.water.texturewidth = texturewidth;
5554                 r_fb.water.textureheight = textureheight;
5555                 r_fb.water.camerawidth = camerawidth;
5556                 r_fb.water.cameraheight = cameraheight;
5557         }
5558
5559         if (r_fb.water.texturewidth)
5560         {
5561                 int scaledwidth, scaledheight;
5562
5563                 r_fb.water.enabled = true;
5564
5565                 // water resolution is usually reduced
5566                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5567                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5568                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5569
5570                 // set up variables that will be used in shader setup
5571                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5572                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5573                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5574                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5575         }
5576
5577         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5578         r_fb.water.numwaterplanes = 0;
5579 }
5580
5581 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5582 {
5583         int planeindex, bestplaneindex, vertexindex;
5584         vec3_t mins, maxs, normal, center, v, n;
5585         vec_t planescore, bestplanescore;
5586         mplane_t plane;
5587         r_waterstate_waterplane_t *p;
5588         texture_t *t = R_GetCurrentTexture(surface->texture);
5589
5590         rsurface.texture = t;
5591         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5592         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5593         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5594                 return;
5595         // average the vertex normals, find the surface bounds (after deformvertexes)
5596         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5597         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5598         VectorCopy(n, normal);
5599         VectorCopy(v, mins);
5600         VectorCopy(v, maxs);
5601         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5602         {
5603                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5604                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5605                 VectorAdd(normal, n, normal);
5606                 mins[0] = min(mins[0], v[0]);
5607                 mins[1] = min(mins[1], v[1]);
5608                 mins[2] = min(mins[2], v[2]);
5609                 maxs[0] = max(maxs[0], v[0]);
5610                 maxs[1] = max(maxs[1], v[1]);
5611                 maxs[2] = max(maxs[2], v[2]);
5612         }
5613         VectorNormalize(normal);
5614         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5615
5616         VectorCopy(normal, plane.normal);
5617         VectorNormalize(plane.normal);
5618         plane.dist = DotProduct(center, plane.normal);
5619         PlaneClassify(&plane);
5620         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5621         {
5622                 // skip backfaces (except if nocullface is set)
5623 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5624 //                      return;
5625                 VectorNegate(plane.normal, plane.normal);
5626                 plane.dist *= -1;
5627                 PlaneClassify(&plane);
5628         }
5629
5630
5631         // find a matching plane if there is one
5632         bestplaneindex = -1;
5633         bestplanescore = 1048576.0f;
5634         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5635         {
5636                 if(p->camera_entity == t->camera_entity)
5637                 {
5638                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5639                         if (bestplaneindex < 0 || bestplanescore > planescore)
5640                         {
5641                                 bestplaneindex = planeindex;
5642                                 bestplanescore = planescore;
5643                         }
5644                 }
5645         }
5646         planeindex = bestplaneindex;
5647         p = r_fb.water.waterplanes + planeindex;
5648
5649         // if this surface does not fit any known plane rendered this frame, add one
5650         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5651         {
5652                 // store the new plane
5653                 planeindex = r_fb.water.numwaterplanes++;
5654                 p = r_fb.water.waterplanes + planeindex;
5655                 p->plane = plane;
5656                 // clear materialflags and pvs
5657                 p->materialflags = 0;
5658                 p->pvsvalid = false;
5659                 p->camera_entity = t->camera_entity;
5660                 VectorCopy(mins, p->mins);
5661                 VectorCopy(maxs, p->maxs);
5662         }
5663         else
5664         {
5665                 // merge mins/maxs when we're adding this surface to the plane
5666                 p->mins[0] = min(p->mins[0], mins[0]);
5667                 p->mins[1] = min(p->mins[1], mins[1]);
5668                 p->mins[2] = min(p->mins[2], mins[2]);
5669                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5670                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5671                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5672         }
5673         // merge this surface's materialflags into the waterplane
5674         p->materialflags |= t->currentmaterialflags;
5675         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5676         {
5677                 // merge this surface's PVS into the waterplane
5678                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5679                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5680                 {
5681                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5682                         p->pvsvalid = true;
5683                 }
5684         }
5685 }
5686
5687 extern cvar_t r_drawparticles;
5688 extern cvar_t r_drawdecals;
5689
5690 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5691 {
5692         int myscissor[4];
5693         r_refdef_view_t originalview;
5694         r_refdef_view_t myview;
5695         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;
5696         r_waterstate_waterplane_t *p;
5697         vec3_t visorigin;
5698         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5699         char vabuf[1024];
5700
5701         originalview = r_refdef.view;
5702
5703         // lowquality hack, temporarily shut down some cvars and restore afterwards
5704         qualityreduction = r_water_lowquality.integer;
5705         if (qualityreduction > 0)
5706         {
5707                 if (qualityreduction >= 1)
5708                 {
5709                         old_r_shadows = r_shadows.integer;
5710                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5711                         old_r_dlight = r_shadow_realtime_dlight.integer;
5712                         Cvar_SetValueQuick(&r_shadows, 0);
5713                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5714                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5715                 }
5716                 if (qualityreduction >= 2)
5717                 {
5718                         old_r_dynamic = r_dynamic.integer;
5719                         old_r_particles = r_drawparticles.integer;
5720                         old_r_decals = r_drawdecals.integer;
5721                         Cvar_SetValueQuick(&r_dynamic, 0);
5722                         Cvar_SetValueQuick(&r_drawparticles, 0);
5723                         Cvar_SetValueQuick(&r_drawdecals, 0);
5724                 }
5725         }
5726
5727         // make sure enough textures are allocated
5728         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5729         {
5730                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5731                 {
5732                         if (!p->texture_refraction)
5733                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5734                         if (!p->texture_refraction)
5735                                 goto error;
5736                         if (usewaterfbo)
5737                         {
5738                                 if (r_fb.water.depthtexture == NULL)
5739                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5740                                 if (p->fbo_refraction == 0)
5741                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5742                         }
5743                 }
5744                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5745                 {
5746                         if (!p->texture_camera)
5747                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5748                         if (!p->texture_camera)
5749                                 goto error;
5750                         if (usewaterfbo)
5751                         {
5752                                 if (r_fb.water.depthtexture == NULL)
5753                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5754                                 if (p->fbo_camera == 0)
5755                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5756                         }
5757                 }
5758
5759                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5760                 {
5761                         if (!p->texture_reflection)
5762                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5763                         if (!p->texture_reflection)
5764                                 goto error;
5765                         if (usewaterfbo)
5766                         {
5767                                 if (r_fb.water.depthtexture == NULL)
5768                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5769                                 if (p->fbo_reflection == 0)
5770                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5771                         }
5772                 }
5773         }
5774
5775         // render views
5776         r_refdef.view = originalview;
5777         r_refdef.view.showdebug = false;
5778         r_refdef.view.width = r_fb.water.waterwidth;
5779         r_refdef.view.height = r_fb.water.waterheight;
5780         r_refdef.view.useclipplane = true;
5781         myview = r_refdef.view;
5782         r_fb.water.renderingscene = true;
5783         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5784         {
5785                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5786                 {
5787                         r_refdef.view = myview;
5788                         if(r_water_scissormode.integer)
5789                         {
5790                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5791                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5792                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5793                         }
5794
5795                         // render reflected scene and copy into texture
5796                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5797                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5798                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5799                         r_refdef.view.clipplane = p->plane;
5800                         // reverse the cullface settings for this render
5801                         r_refdef.view.cullface_front = GL_FRONT;
5802                         r_refdef.view.cullface_back = GL_BACK;
5803                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5804                         {
5805                                 r_refdef.view.usecustompvs = true;
5806                                 if (p->pvsvalid)
5807                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5808                                 else
5809                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5810                         }
5811
5812                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5813                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5814                         R_ClearScreen(r_refdef.fogenabled);
5815                         if(r_water_scissormode.integer & 2)
5816                                 R_View_UpdateWithScissor(myscissor);
5817                         else
5818                                 R_View_Update();
5819                         if(r_water_scissormode.integer & 1)
5820                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5821                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5822
5823                         if (!p->fbo_reflection)
5824                                 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);
5825                         r_fb.water.hideplayer = false;
5826                 }
5827
5828                 // render the normal view scene and copy into texture
5829                 // (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)
5830                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5831                 {
5832                         r_refdef.view = myview;
5833                         if(r_water_scissormode.integer)
5834                         {
5835                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5836                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5837                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5838                         }
5839
5840                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5841
5842                         r_refdef.view.clipplane = p->plane;
5843                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5844                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5845
5846                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5847                         {
5848                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5849                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5850                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5851                                 R_RenderView_UpdateViewVectors();
5852                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5853                                 {
5854                                         r_refdef.view.usecustompvs = true;
5855                                         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);
5856                                 }
5857                         }
5858
5859                         PlaneClassify(&r_refdef.view.clipplane);
5860
5861                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5862                         R_ClearScreen(r_refdef.fogenabled);
5863                         if(r_water_scissormode.integer & 2)
5864                                 R_View_UpdateWithScissor(myscissor);
5865                         else
5866                                 R_View_Update();
5867                         if(r_water_scissormode.integer & 1)
5868                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5869                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5870
5871                         if (!p->fbo_refraction)
5872                                 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);
5873                         r_fb.water.hideplayer = false;
5874                 }
5875                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5876                 {
5877                         r_refdef.view = myview;
5878
5879                         r_refdef.view.clipplane = p->plane;
5880                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5881                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5882
5883                         r_refdef.view.width = r_fb.water.camerawidth;
5884                         r_refdef.view.height = r_fb.water.cameraheight;
5885                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5886                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5887                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5888                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5889
5890                         if(p->camera_entity)
5891                         {
5892                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5893                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5894                         }
5895
5896                         // note: all of the view is used for displaying... so
5897                         // there is no use in scissoring
5898
5899                         // reverse the cullface settings for this render
5900                         r_refdef.view.cullface_front = GL_FRONT;
5901                         r_refdef.view.cullface_back = GL_BACK;
5902                         // also reverse the view matrix
5903                         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
5904                         R_RenderView_UpdateViewVectors();
5905                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5906                         {
5907                                 r_refdef.view.usecustompvs = true;
5908                                 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);
5909                         }
5910                         
5911                         // camera needs no clipplane
5912                         r_refdef.view.useclipplane = false;
5913
5914                         PlaneClassify(&r_refdef.view.clipplane);
5915
5916                         r_fb.water.hideplayer = false;
5917
5918                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5919                         R_ClearScreen(r_refdef.fogenabled);
5920                         R_View_Update();
5921                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5922
5923                         if (!p->fbo_camera)
5924                                 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);
5925                         r_fb.water.hideplayer = false;
5926                 }
5927
5928         }
5929         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5930         r_fb.water.renderingscene = false;
5931         r_refdef.view = originalview;
5932         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5933         if (!r_fb.water.depthtexture)
5934                 R_ClearScreen(r_refdef.fogenabled);
5935         R_View_Update();
5936         goto finish;
5937 error:
5938         r_refdef.view = originalview;
5939         r_fb.water.renderingscene = false;
5940         Cvar_SetValueQuick(&r_water, 0);
5941         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5942 finish:
5943         // lowquality hack, restore cvars
5944         if (qualityreduction > 0)
5945         {
5946                 if (qualityreduction >= 1)
5947                 {
5948                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5949                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5950                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5951                 }
5952                 if (qualityreduction >= 2)
5953                 {
5954                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5955                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5956                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5957                 }
5958         }
5959 }
5960
5961 static void R_Bloom_StartFrame(void)
5962 {
5963         int i;
5964         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5965         int viewwidth, viewheight;
5966         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5967         textype_t textype = TEXTYPE_COLORBUFFER;
5968
5969         switch (vid.renderpath)
5970         {
5971         case RENDERPATH_GL20:
5972         case RENDERPATH_GLES2:
5973                 if (vid.support.ext_framebuffer_object)
5974                 {
5975                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5976                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5977                 }
5978                 break;
5979         case RENDERPATH_GL11:
5980         case RENDERPATH_GL13:
5981         case RENDERPATH_GLES1:
5982         case RENDERPATH_D3D9:
5983         case RENDERPATH_D3D10:
5984         case RENDERPATH_D3D11:
5985         case RENDERPATH_SOFT:
5986                 break;
5987         }
5988
5989         if (r_viewscale_fpsscaling.integer)
5990         {
5991                 double actualframetime;
5992                 double targetframetime;
5993                 double adjust;
5994                 actualframetime = r_refdef.lastdrawscreentime;
5995                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5996                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5997                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5998                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5999                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6000                 viewscalefpsadjusted += adjust;
6001                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6002         }
6003         else
6004                 viewscalefpsadjusted = 1.0f;
6005
6006         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6007
6008         switch(vid.renderpath)
6009         {
6010         case RENDERPATH_GL20:
6011         case RENDERPATH_D3D9:
6012         case RENDERPATH_D3D10:
6013         case RENDERPATH_D3D11:
6014         case RENDERPATH_SOFT:
6015         case RENDERPATH_GLES2:
6016                 break;
6017         case RENDERPATH_GL11:
6018         case RENDERPATH_GL13:
6019         case RENDERPATH_GLES1:
6020                 return;
6021         }
6022
6023         // set bloomwidth and bloomheight to the bloom resolution that will be
6024         // used (often less than the screen resolution for faster rendering)
6025         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6026         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6027         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6028         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6029         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6030
6031         // calculate desired texture sizes
6032         if (vid.support.arb_texture_non_power_of_two)
6033         {
6034                 screentexturewidth = vid.width;
6035                 screentextureheight = vid.height;
6036                 bloomtexturewidth = r_fb.bloomwidth;
6037                 bloomtextureheight = r_fb.bloomheight;
6038         }
6039         else
6040         {
6041                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6042                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6043                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6044                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6045         }
6046
6047         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))
6048         {
6049                 Cvar_SetValueQuick(&r_bloom, 0);
6050                 Cvar_SetValueQuick(&r_motionblur, 0);
6051                 Cvar_SetValueQuick(&r_damageblur, 0);
6052         }
6053
6054         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6055          && !r_bloom.integer
6056          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6057          && !useviewfbo
6058          && r_viewscale.value == 1.0f
6059          && !r_viewscale_fpsscaling.integer)
6060                 screentexturewidth = screentextureheight = 0;
6061         if (!r_bloom.integer)
6062                 bloomtexturewidth = bloomtextureheight = 0;
6063
6064         // allocate textures as needed
6065         if (r_fb.screentexturewidth != screentexturewidth
6066          || r_fb.screentextureheight != screentextureheight
6067          || r_fb.bloomtexturewidth != bloomtexturewidth
6068          || r_fb.bloomtextureheight != bloomtextureheight
6069          || r_fb.textype != textype
6070          || useviewfbo != (r_fb.fbo != 0))
6071         {
6072                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6073                 {
6074                         if (r_fb.bloomtexture[i])
6075                                 R_FreeTexture(r_fb.bloomtexture[i]);
6076                         r_fb.bloomtexture[i] = NULL;
6077
6078                         if (r_fb.bloomfbo[i])
6079                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6080                         r_fb.bloomfbo[i] = 0;
6081                 }
6082
6083                 if (r_fb.fbo)
6084                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6085                 r_fb.fbo = 0;
6086
6087                 if (r_fb.colortexture)
6088                         R_FreeTexture(r_fb.colortexture);
6089                 r_fb.colortexture = NULL;
6090
6091                 if (r_fb.depthtexture)
6092                         R_FreeTexture(r_fb.depthtexture);
6093                 r_fb.depthtexture = NULL;
6094
6095                 if (r_fb.ghosttexture)
6096                         R_FreeTexture(r_fb.ghosttexture);
6097                 r_fb.ghosttexture = NULL;
6098
6099                 r_fb.screentexturewidth = screentexturewidth;
6100                 r_fb.screentextureheight = screentextureheight;
6101                 r_fb.bloomtexturewidth = bloomtexturewidth;
6102                 r_fb.bloomtextureheight = bloomtextureheight;
6103                 r_fb.textype = textype;
6104
6105                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6106                 {
6107                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6108                                 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);
6109                         r_fb.ghosttexture_valid = false;
6110                         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);
6111                         if (useviewfbo)
6112                         {
6113                                 // FIXME: choose depth bits based on a cvar
6114                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false, vid.support.ext_packed_depth_stencil);
6115                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6116                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6117 #ifndef USE_GLES2
6118                                 // render depth into one texture and color into the other
6119                                 if (qglDrawBuffer)
6120                                 {
6121                                         int status;
6122                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6123                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6124                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6125                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6126                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6127                                 }
6128 #endif
6129                         }
6130                 }
6131
6132                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6133                 {
6134                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6135                         {
6136                                 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);
6137                                 if (useviewfbo)
6138                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6139                         }
6140                 }
6141         }
6142
6143         // bloom texture is a different resolution
6144         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6145         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6146         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6147         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6148         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6149
6150         // set up a texcoord array for the full resolution screen image
6151         // (we have to keep this around to copy back during final render)
6152         r_fb.screentexcoord2f[0] = 0;
6153         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6154         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6155         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6156         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6157         r_fb.screentexcoord2f[5] = 0;
6158         r_fb.screentexcoord2f[6] = 0;
6159         r_fb.screentexcoord2f[7] = 0;
6160
6161         // set up a texcoord array for the reduced resolution bloom image
6162         // (which will be additive blended over the screen image)
6163         r_fb.bloomtexcoord2f[0] = 0;
6164         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6165         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6166         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6167         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6168         r_fb.bloomtexcoord2f[5] = 0;
6169         r_fb.bloomtexcoord2f[6] = 0;
6170         r_fb.bloomtexcoord2f[7] = 0;
6171
6172         switch(vid.renderpath)
6173         {
6174         case RENDERPATH_GL11:
6175         case RENDERPATH_GL13:
6176         case RENDERPATH_GL20:
6177         case RENDERPATH_SOFT:
6178         case RENDERPATH_GLES1:
6179         case RENDERPATH_GLES2:
6180                 break;
6181         case RENDERPATH_D3D9:
6182         case RENDERPATH_D3D10:
6183         case RENDERPATH_D3D11:
6184                 {
6185                         int i;
6186                         for (i = 0;i < 4;i++)
6187                         {
6188                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6189                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6190                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6191                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6192                         }
6193                 }
6194                 break;
6195         }
6196
6197         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);
6198
6199         if (r_fb.fbo)
6200                 r_refdef.view.clear = true;
6201 }
6202
6203 static void R_Bloom_MakeTexture(void)
6204 {
6205         int x, range, dir;
6206         float xoffset, yoffset, r, brighten;
6207         rtexture_t *intex;
6208         float colorscale = r_bloom_colorscale.value;
6209
6210         r_refdef.stats.bloom++;
6211
6212         if (!r_fb.fbo)
6213         {
6214                 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);
6215                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6216         }
6217
6218         // scale down screen texture to the bloom texture size
6219         CHECKGLERROR
6220         r_fb.bloomindex = 0;
6221         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6222         R_SetViewport(&r_fb.bloomviewport);
6223         GL_BlendFunc(GL_ONE, GL_ZERO);
6224         GL_Color(colorscale, colorscale, colorscale, 1);
6225         // 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...
6226         switch(vid.renderpath)
6227         {
6228         case RENDERPATH_GL11:
6229         case RENDERPATH_GL13:
6230         case RENDERPATH_GL20:
6231         case RENDERPATH_GLES1:
6232         case RENDERPATH_GLES2:
6233         case RENDERPATH_SOFT:
6234                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6235                 break;
6236         case RENDERPATH_D3D9:
6237         case RENDERPATH_D3D10:
6238         case RENDERPATH_D3D11:
6239                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6240                 break;
6241         }
6242         // TODO: do boxfilter scale-down in shader?
6243         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6244         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6245         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6246
6247         // we now have a properly scaled bloom image
6248         if (!r_fb.bloomfbo[r_fb.bloomindex])
6249         {
6250                 // copy it into the bloom texture
6251                 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);
6252                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6253         }
6254
6255         // multiply bloom image by itself as many times as desired
6256         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6257         {
6258                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6259                 r_fb.bloomindex ^= 1;
6260                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6261                 x *= 2;
6262                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6263                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6264                 GL_Color(r,r,r,1);
6265                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6266                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6267                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6268                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6269
6270                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6271                 {
6272                         // copy the darkened image to a texture
6273                         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);
6274                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6275                 }
6276         }
6277
6278         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6279         brighten = r_bloom_brighten.value;
6280         brighten = sqrt(brighten);
6281         if(range >= 1)
6282                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6283
6284         for (dir = 0;dir < 2;dir++)
6285         {
6286                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6287                 r_fb.bloomindex ^= 1;
6288                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6289                 // blend on at multiple vertical offsets to achieve a vertical blur
6290                 // TODO: do offset blends using GLSL
6291                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6292                 GL_BlendFunc(GL_ONE, GL_ZERO);
6293                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6294                 for (x = -range;x <= range;x++)
6295                 {
6296                         if (!dir){xoffset = 0;yoffset = x;}
6297                         else {xoffset = x;yoffset = 0;}
6298                         xoffset /= (float)r_fb.bloomtexturewidth;
6299                         yoffset /= (float)r_fb.bloomtextureheight;
6300                         // compute a texcoord array with the specified x and y offset
6301                         r_fb.offsettexcoord2f[0] = xoffset+0;
6302                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6303                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6304                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6305                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6306                         r_fb.offsettexcoord2f[5] = yoffset+0;
6307                         r_fb.offsettexcoord2f[6] = xoffset+0;
6308                         r_fb.offsettexcoord2f[7] = yoffset+0;
6309                         // this r value looks like a 'dot' particle, fading sharply to
6310                         // black at the edges
6311                         // (probably not realistic but looks good enough)
6312                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6313                         //r = brighten/(range*2+1);
6314                         r = brighten / (range * 2 + 1);
6315                         if(range >= 1)
6316                                 r *= (1 - x*x/(float)(range*range));
6317                         GL_Color(r, r, r, 1);
6318                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6319                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6320                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6321                         GL_BlendFunc(GL_ONE, GL_ONE);
6322                 }
6323
6324                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6325                 {
6326                         // copy the vertically or horizontally blurred bloom view to a texture
6327                         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);
6328                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6329                 }
6330         }
6331 }
6332
6333 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6334 {
6335         unsigned int permutation;
6336         float uservecs[4][4];
6337
6338         switch (vid.renderpath)
6339         {
6340         case RENDERPATH_GL20:
6341         case RENDERPATH_D3D9:
6342         case RENDERPATH_D3D10:
6343         case RENDERPATH_D3D11:
6344         case RENDERPATH_SOFT:
6345         case RENDERPATH_GLES2:
6346                 permutation =
6347                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6348                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6349                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6350                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6351                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6352
6353                 if (r_fb.colortexture)
6354                 {
6355                         if (!r_fb.fbo)
6356                         {
6357                                 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);
6358                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6359                         }
6360
6361                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6362                         {
6363                                 // declare variables
6364                                 float blur_factor, blur_mouseaccel, blur_velocity;
6365                                 static float blur_average; 
6366                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6367
6368                                 // set a goal for the factoring
6369                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6370                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6371                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6372                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6373                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6374                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6375
6376                                 // from the goal, pick an averaged value between goal and last value
6377                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6378                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6379
6380                                 // enforce minimum amount of blur 
6381                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6382
6383                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6384
6385                                 // calculate values into a standard alpha
6386                                 cl.motionbluralpha = 1 - exp(-
6387                                                 (
6388                                                  (r_motionblur.value * blur_factor / 80)
6389                                                  +
6390                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6391                                                 )
6392                                                 /
6393                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6394                                           );
6395
6396                                 // randomization for the blur value to combat persistent ghosting
6397                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6398                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6399
6400                                 // apply the blur
6401                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6402                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6403                                 {
6404                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6405                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6406                                         switch(vid.renderpath)
6407                                         {
6408                                         case RENDERPATH_GL11:
6409                                         case RENDERPATH_GL13:
6410                                         case RENDERPATH_GL20:
6411                                         case RENDERPATH_GLES1:
6412                                         case RENDERPATH_GLES2:
6413                                         case RENDERPATH_SOFT:
6414                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6415                                                 break;
6416                                         case RENDERPATH_D3D9:
6417                                         case RENDERPATH_D3D10:
6418                                         case RENDERPATH_D3D11:
6419                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6420                                                 break;
6421                                         }
6422                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6423                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6424                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6425                                 }
6426
6427                                 // updates old view angles for next pass
6428                                 VectorCopy(cl.viewangles, blur_oldangles);
6429
6430                                 // copy view into the ghost texture
6431                                 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);
6432                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6433                                 r_fb.ghosttexture_valid = true;
6434                         }
6435                 }
6436                 else
6437                 {
6438                         // no r_fb.colortexture means we're rendering to the real fb
6439                         // we may still have to do view tint...
6440                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6441                         {
6442                                 // apply a color tint to the whole view
6443                                 R_ResetViewRendering2D(0, NULL, NULL);
6444                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6445                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6446                                 R_SetupShader_Generic_NoTexture(false, true);
6447                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6448                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6449                         }
6450                         break; // no screen processing, no bloom, skip it
6451                 }
6452
6453                 if (r_fb.bloomtexture[0])
6454                 {
6455                         // make the bloom texture
6456                         R_Bloom_MakeTexture();
6457                 }
6458
6459 #if _MSC_VER >= 1400
6460 #define sscanf sscanf_s
6461 #endif
6462                 memset(uservecs, 0, sizeof(uservecs));
6463                 if (r_glsl_postprocess_uservec1_enable.integer)
6464                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6465                 if (r_glsl_postprocess_uservec2_enable.integer)
6466                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6467                 if (r_glsl_postprocess_uservec3_enable.integer)
6468                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6469                 if (r_glsl_postprocess_uservec4_enable.integer)
6470                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6471
6472                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6473                 GL_Color(1, 1, 1, 1);
6474                 GL_BlendFunc(GL_ONE, GL_ZERO);
6475
6476                 switch(vid.renderpath)
6477                 {
6478                 case RENDERPATH_GL20:
6479                 case RENDERPATH_GLES2:
6480                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6481                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6482                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6483                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6484                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6485                         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]);
6486                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6487                         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]);
6488                         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]);
6489                         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]);
6490                         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]);
6491                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6492                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6493                         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);
6494                         break;
6495                 case RENDERPATH_D3D9:
6496 #ifdef SUPPORTD3D
6497                         // 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...
6498                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6499                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6500                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6501                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6502                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6503                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6504                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6505                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6506                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6507                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6508                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6509                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6510                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6511                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6512 #endif
6513                         break;
6514                 case RENDERPATH_D3D10:
6515                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6516                         break;
6517                 case RENDERPATH_D3D11:
6518                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6519                         break;
6520                 case RENDERPATH_SOFT:
6521                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6522                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6523                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6524                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6525                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6526                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6527                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6528                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6529                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6530                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6531                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6532                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6533                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6534                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6535                         break;
6536                 default:
6537                         break;
6538                 }
6539                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6540                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6541                 break;
6542         case RENDERPATH_GL11:
6543         case RENDERPATH_GL13:
6544         case RENDERPATH_GLES1:
6545                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6546                 {
6547                         // apply a color tint to the whole view
6548                         R_ResetViewRendering2D(0, NULL, NULL);
6549                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6550                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6551                         R_SetupShader_Generic_NoTexture(false, true);
6552                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6553                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6554                 }
6555                 break;
6556         }
6557 }
6558
6559 matrix4x4_t r_waterscrollmatrix;
6560
6561 void R_UpdateFog(void)
6562 {
6563         // Nehahra fog
6564         if (gamemode == GAME_NEHAHRA)
6565         {
6566                 if (gl_fogenable.integer)
6567                 {
6568                         r_refdef.oldgl_fogenable = true;
6569                         r_refdef.fog_density = gl_fogdensity.value;
6570                         r_refdef.fog_red = gl_fogred.value;
6571                         r_refdef.fog_green = gl_foggreen.value;
6572                         r_refdef.fog_blue = gl_fogblue.value;
6573                         r_refdef.fog_alpha = 1;
6574                         r_refdef.fog_start = 0;
6575                         r_refdef.fog_end = gl_skyclip.value;
6576                         r_refdef.fog_height = 1<<30;
6577                         r_refdef.fog_fadedepth = 128;
6578                 }
6579                 else if (r_refdef.oldgl_fogenable)
6580                 {
6581                         r_refdef.oldgl_fogenable = false;
6582                         r_refdef.fog_density = 0;
6583                         r_refdef.fog_red = 0;
6584                         r_refdef.fog_green = 0;
6585                         r_refdef.fog_blue = 0;
6586                         r_refdef.fog_alpha = 0;
6587                         r_refdef.fog_start = 0;
6588                         r_refdef.fog_end = 0;
6589                         r_refdef.fog_height = 1<<30;
6590                         r_refdef.fog_fadedepth = 128;
6591                 }
6592         }
6593
6594         // fog parms
6595         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6596         r_refdef.fog_start = max(0, r_refdef.fog_start);
6597         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6598
6599         if (r_refdef.fog_density && r_drawfog.integer)
6600         {
6601                 r_refdef.fogenabled = true;
6602                 // this is the point where the fog reaches 0.9986 alpha, which we
6603                 // consider a good enough cutoff point for the texture
6604                 // (0.9986 * 256 == 255.6)
6605                 if (r_fog_exp2.integer)
6606                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6607                 else
6608                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6609                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6610                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6611                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6612                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6613                         R_BuildFogHeightTexture();
6614                 // fog color was already set
6615                 // update the fog texture
6616                 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)
6617                         R_BuildFogTexture();
6618                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6619                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6620         }
6621         else
6622                 r_refdef.fogenabled = false;
6623
6624         // fog color
6625         if (r_refdef.fog_density)
6626         {
6627                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6628                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6629                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6630
6631                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6632                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6633                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6634                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6635
6636                 {
6637                         vec3_t fogvec;
6638                         VectorCopy(r_refdef.fogcolor, fogvec);
6639                         //   color.rgb *= ContrastBoost * SceneBrightness;
6640                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6641                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6642                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6643                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6644                 }
6645         }
6646 }
6647
6648 void R_UpdateVariables(void)
6649 {
6650         R_Textures_Frame();
6651
6652         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6653
6654         r_refdef.farclip = r_farclip_base.value;
6655         if (r_refdef.scene.worldmodel)
6656                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6657         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6658
6659         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6660                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6661         r_refdef.polygonfactor = 0;
6662         r_refdef.polygonoffset = 0;
6663         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6664         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6665
6666         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6667         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6668         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6669         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6670         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6671         if (FAKELIGHT_ENABLED)
6672         {
6673                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6674         }
6675         if (r_showsurfaces.integer)
6676         {
6677                 r_refdef.scene.rtworld = false;
6678                 r_refdef.scene.rtworldshadows = false;
6679                 r_refdef.scene.rtdlight = false;
6680                 r_refdef.scene.rtdlightshadows = false;
6681                 r_refdef.lightmapintensity = 0;
6682         }
6683
6684         switch(vid.renderpath)
6685         {
6686         case RENDERPATH_GL20:
6687         case RENDERPATH_D3D9:
6688         case RENDERPATH_D3D10:
6689         case RENDERPATH_D3D11:
6690         case RENDERPATH_SOFT:
6691         case RENDERPATH_GLES2:
6692                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6693                 {
6694                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6695                         {
6696                                 // build GLSL gamma texture
6697 #define RAMPWIDTH 256
6698                                 unsigned short ramp[RAMPWIDTH * 3];
6699                                 unsigned char rampbgr[RAMPWIDTH][4];
6700                                 int i;
6701
6702                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6703
6704                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6705                                 for(i = 0; i < RAMPWIDTH; ++i)
6706                                 {
6707                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6708                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6709                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6710                                         rampbgr[i][3] = 0;
6711                                 }
6712                                 if (r_texture_gammaramps)
6713                                 {
6714                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6715                                 }
6716                                 else
6717                                 {
6718                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6719                                 }
6720                         }
6721                 }
6722                 else
6723                 {
6724                         // remove GLSL gamma texture
6725                 }
6726                 break;
6727         case RENDERPATH_GL11:
6728         case RENDERPATH_GL13:
6729         case RENDERPATH_GLES1:
6730                 break;
6731         }
6732 }
6733
6734 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6735 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6736 /*
6737 ================
6738 R_SelectScene
6739 ================
6740 */
6741 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6742         if( scenetype != r_currentscenetype ) {
6743                 // store the old scenetype
6744                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6745                 r_currentscenetype = scenetype;
6746                 // move in the new scene
6747                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6748         }
6749 }
6750
6751 /*
6752 ================
6753 R_GetScenePointer
6754 ================
6755 */
6756 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6757 {
6758         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6759         if( scenetype == r_currentscenetype ) {
6760                 return &r_refdef.scene;
6761         } else {
6762                 return &r_scenes_store[ scenetype ];
6763         }
6764 }
6765
6766 static int R_SortEntities_Compare(const void *ap, const void *bp)
6767 {
6768         const entity_render_t *a = *(const entity_render_t **)ap;
6769         const entity_render_t *b = *(const entity_render_t **)bp;
6770
6771         // 1. compare model
6772         if(a->model < b->model)
6773                 return -1;
6774         if(a->model > b->model)
6775                 return +1;
6776
6777         // 2. compare skin
6778         // TODO possibly calculate the REAL skinnum here first using
6779         // skinscenes?
6780         if(a->skinnum < b->skinnum)
6781                 return -1;
6782         if(a->skinnum > b->skinnum)
6783                 return +1;
6784
6785         // everything we compared is equal
6786         return 0;
6787 }
6788 static void R_SortEntities(void)
6789 {
6790         // below or equal 2 ents, sorting never gains anything
6791         if(r_refdef.scene.numentities <= 2)
6792                 return;
6793         // sort
6794         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6795 }
6796
6797 /*
6798 ================
6799 R_RenderView
6800 ================
6801 */
6802 int dpsoftrast_test;
6803 extern cvar_t r_shadow_bouncegrid;
6804 void R_RenderView(void)
6805 {
6806         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6807         int fbo;
6808         rtexture_t *depthtexture;
6809         rtexture_t *colortexture;
6810
6811         dpsoftrast_test = r_test.integer;
6812
6813         if (r_timereport_active)
6814                 R_TimeReport("start");
6815         r_textureframe++; // used only by R_GetCurrentTexture
6816         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6817
6818         if(R_CompileShader_CheckStaticParms())
6819                 R_GLSL_Restart_f();
6820
6821         if (!r_drawentities.integer)
6822                 r_refdef.scene.numentities = 0;
6823         else if (r_sortentities.integer)
6824                 R_SortEntities();
6825
6826         R_AnimCache_ClearCache();
6827         R_FrameData_NewFrame();
6828
6829         /* adjust for stereo display */
6830         if(R_Stereo_Active())
6831         {
6832                 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);
6833                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6834         }
6835
6836         if (r_refdef.view.isoverlay)
6837         {
6838                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6839                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6840                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6841                 R_TimeReport("depthclear");
6842
6843                 r_refdef.view.showdebug = false;
6844
6845                 r_fb.water.enabled = false;
6846                 r_fb.water.numwaterplanes = 0;
6847
6848                 R_RenderScene(0, NULL, NULL);
6849
6850                 r_refdef.view.matrix = originalmatrix;
6851
6852                 CHECKGLERROR
6853                 return;
6854         }
6855
6856         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6857         {
6858                 r_refdef.view.matrix = originalmatrix;
6859                 return;
6860         }
6861
6862         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6863
6864         R_RenderView_UpdateViewVectors();
6865
6866         R_Shadow_UpdateWorldLightSelection();
6867
6868         R_Bloom_StartFrame();
6869         R_Water_StartFrame();
6870
6871         // now we probably have an fbo to render into
6872         fbo = r_fb.fbo;
6873         depthtexture = r_fb.depthtexture;
6874         colortexture = r_fb.colortexture;
6875
6876         CHECKGLERROR
6877         if (r_timereport_active)
6878                 R_TimeReport("viewsetup");
6879
6880         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6881
6882         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6883         {
6884                 R_ClearScreen(r_refdef.fogenabled);
6885                 if (r_timereport_active)
6886                         R_TimeReport("viewclear");
6887         }
6888         r_refdef.view.clear = true;
6889
6890         r_refdef.view.showdebug = true;
6891
6892         R_View_Update();
6893         if (r_timereport_active)
6894                 R_TimeReport("visibility");
6895
6896         R_Shadow_UpdateBounceGridTexture();
6897         if (r_timereport_active && r_shadow_bouncegrid.integer)
6898                 R_TimeReport("bouncegrid");
6899
6900         r_fb.water.numwaterplanes = 0;
6901         if (r_fb.water.enabled)
6902                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6903
6904         R_RenderScene(fbo, depthtexture, colortexture);
6905         r_fb.water.numwaterplanes = 0;
6906
6907         R_BlendView(fbo, depthtexture, colortexture);
6908         if (r_timereport_active)
6909                 R_TimeReport("blendview");
6910
6911         GL_Scissor(0, 0, vid.width, vid.height);
6912         GL_ScissorTest(false);
6913
6914         r_refdef.view.matrix = originalmatrix;
6915
6916         CHECKGLERROR
6917 }
6918
6919 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6920 {
6921         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6922         {
6923                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6924                 if (r_timereport_active)
6925                         R_TimeReport("waterworld");
6926         }
6927
6928         // don't let sound skip if going slow
6929         if (r_refdef.scene.extraupdate)
6930                 S_ExtraUpdate ();
6931
6932         R_DrawModelsAddWaterPlanes();
6933         if (r_timereport_active)
6934                 R_TimeReport("watermodels");
6935
6936         if (r_fb.water.numwaterplanes)
6937         {
6938                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6939                 if (r_timereport_active)
6940                         R_TimeReport("waterscenes");
6941         }
6942 }
6943
6944 extern cvar_t cl_locs_show;
6945 static void R_DrawLocs(void);
6946 static void R_DrawEntityBBoxes(void);
6947 static void R_DrawModelDecals(void);
6948 extern cvar_t cl_decals_newsystem;
6949 extern qboolean r_shadow_usingdeferredprepass;
6950 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6951 {
6952         qboolean shadowmapping = false;
6953
6954         if (r_timereport_active)
6955                 R_TimeReport("beginscene");
6956
6957         r_refdef.stats.renders++;
6958
6959         R_UpdateFog();
6960
6961         // don't let sound skip if going slow
6962         if (r_refdef.scene.extraupdate)
6963                 S_ExtraUpdate ();
6964
6965         R_MeshQueue_BeginScene();
6966
6967         R_SkyStartFrame();
6968
6969         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);
6970
6971         if (r_timereport_active)
6972                 R_TimeReport("skystartframe");
6973
6974         if (cl.csqc_vidvars.drawworld)
6975         {
6976                 // don't let sound skip if going slow
6977                 if (r_refdef.scene.extraupdate)
6978                         S_ExtraUpdate ();
6979
6980                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6981                 {
6982                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6983                         if (r_timereport_active)
6984                                 R_TimeReport("worldsky");
6985                 }
6986
6987                 if (R_DrawBrushModelsSky() && r_timereport_active)
6988                         R_TimeReport("bmodelsky");
6989
6990                 if (skyrendermasked && skyrenderlater)
6991                 {
6992                         // we have to force off the water clipping plane while rendering sky
6993                         R_SetupView(false, fbo, depthtexture, colortexture);
6994                         R_Sky();
6995                         R_SetupView(true, fbo, depthtexture, colortexture);
6996                         if (r_timereport_active)
6997                                 R_TimeReport("sky");
6998                 }
6999         }
7000
7001         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7002         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7003                 R_Shadow_PrepareModelShadows();
7004         if (r_timereport_active)
7005                 R_TimeReport("preparelights");
7006
7007         if (R_Shadow_ShadowMappingEnabled())
7008                 shadowmapping = true;
7009
7010         if (r_shadow_usingdeferredprepass)
7011                 R_Shadow_DrawPrepass();
7012
7013         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7014         {
7015                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7016                 if (r_timereport_active)
7017                         R_TimeReport("worlddepth");
7018         }
7019         if (r_depthfirst.integer >= 2)
7020         {
7021                 R_DrawModelsDepth();
7022                 if (r_timereport_active)
7023                         R_TimeReport("modeldepth");
7024         }
7025
7026         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7027         {
7028                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7029                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7030                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7031                 // don't let sound skip if going slow
7032                 if (r_refdef.scene.extraupdate)
7033                         S_ExtraUpdate ();
7034         }
7035
7036         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7037         {
7038                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7039                 if (r_timereport_active)
7040                         R_TimeReport("world");
7041         }
7042
7043         // don't let sound skip if going slow
7044         if (r_refdef.scene.extraupdate)
7045                 S_ExtraUpdate ();
7046
7047         R_DrawModels();
7048         if (r_timereport_active)
7049                 R_TimeReport("models");
7050
7051         // don't let sound skip if going slow
7052         if (r_refdef.scene.extraupdate)
7053                 S_ExtraUpdate ();
7054
7055         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7056         {
7057                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7058                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7059                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7060                 // don't let sound skip if going slow
7061                 if (r_refdef.scene.extraupdate)
7062                         S_ExtraUpdate ();
7063         }
7064
7065         if (!r_shadow_usingdeferredprepass)
7066         {
7067                 R_Shadow_DrawLights();
7068                 if (r_timereport_active)
7069                         R_TimeReport("rtlights");
7070         }
7071
7072         // don't let sound skip if going slow
7073         if (r_refdef.scene.extraupdate)
7074                 S_ExtraUpdate ();
7075
7076         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7077         {
7078                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7079                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7080                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7081                 // don't let sound skip if going slow
7082                 if (r_refdef.scene.extraupdate)
7083                         S_ExtraUpdate ();
7084         }
7085
7086         if (cl.csqc_vidvars.drawworld)
7087         {
7088                 if (cl_decals_newsystem.integer)
7089                 {
7090                         R_DrawModelDecals();
7091                         if (r_timereport_active)
7092                                 R_TimeReport("modeldecals");
7093                 }
7094                 else
7095                 {
7096                         R_DrawDecals();
7097                         if (r_timereport_active)
7098                                 R_TimeReport("decals");
7099                 }
7100
7101                 R_DrawParticles();
7102                 if (r_timereport_active)
7103                         R_TimeReport("particles");
7104
7105                 R_DrawExplosions();
7106                 if (r_timereport_active)
7107                         R_TimeReport("explosions");
7108
7109                 R_DrawLightningBeams();
7110                 if (r_timereport_active)
7111                         R_TimeReport("lightning");
7112         }
7113
7114         if (cl.csqc_loaded)
7115                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7116
7117         if (r_refdef.view.showdebug)
7118         {
7119                 if (cl_locs_show.integer)
7120                 {
7121                         R_DrawLocs();
7122                         if (r_timereport_active)
7123                                 R_TimeReport("showlocs");
7124                 }
7125
7126                 if (r_drawportals.integer)
7127                 {
7128                         R_DrawPortals();
7129                         if (r_timereport_active)
7130                                 R_TimeReport("portals");
7131                 }
7132
7133                 if (r_showbboxes.value > 0)
7134                 {
7135                         R_DrawEntityBBoxes();
7136                         if (r_timereport_active)
7137                                 R_TimeReport("bboxes");
7138                 }
7139         }
7140
7141         if (r_transparent.integer)
7142         {
7143                 R_MeshQueue_RenderTransparent();
7144                 if (r_timereport_active)
7145                         R_TimeReport("drawtrans");
7146         }
7147
7148         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))
7149         {
7150                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7151                 if (r_timereport_active)
7152                         R_TimeReport("worlddebug");
7153                 R_DrawModelsDebug();
7154                 if (r_timereport_active)
7155                         R_TimeReport("modeldebug");
7156         }
7157
7158         if (cl.csqc_vidvars.drawworld)
7159         {
7160                 R_Shadow_DrawCoronas();
7161                 if (r_timereport_active)
7162                         R_TimeReport("coronas");
7163         }
7164
7165 #if 0
7166         {
7167                 GL_DepthTest(false);
7168                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7169                 GL_Color(1, 1, 1, 1);
7170                 qglBegin(GL_POLYGON);
7171                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7172                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7173                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7174                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7175                 qglEnd();
7176                 qglBegin(GL_POLYGON);
7177                 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]);
7178                 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]);
7179                 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]);
7180                 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]);
7181                 qglEnd();
7182                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7183         }
7184 #endif
7185
7186         // don't let sound skip if going slow
7187         if (r_refdef.scene.extraupdate)
7188                 S_ExtraUpdate ();
7189 }
7190
7191 static const unsigned short bboxelements[36] =
7192 {
7193         5, 1, 3, 5, 3, 7,
7194         6, 2, 0, 6, 0, 4,
7195         7, 3, 2, 7, 2, 6,
7196         4, 0, 1, 4, 1, 5,
7197         4, 5, 7, 4, 7, 6,
7198         1, 0, 2, 1, 2, 3,
7199 };
7200
7201 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7202 {
7203         int i;
7204         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7205
7206         RSurf_ActiveWorldEntity();
7207
7208         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7209         GL_DepthMask(false);
7210         GL_DepthRange(0, 1);
7211         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7212 //      R_Mesh_ResetTextureState();
7213
7214         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7215         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7216         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7217         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7218         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7219         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7220         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7221         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7222         R_FillColors(color4f, 8, cr, cg, cb, ca);
7223         if (r_refdef.fogenabled)
7224         {
7225                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7226                 {
7227                         f1 = RSurf_FogVertex(v);
7228                         f2 = 1 - f1;
7229                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7230                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7231                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7232                 }
7233         }
7234         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7235         R_Mesh_ResetTextureState();
7236         R_SetupShader_Generic_NoTexture(false, false);
7237         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7238 }
7239
7240 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7241 {
7242         prvm_prog_t *prog = SVVM_prog;
7243         int i;
7244         float color[4];
7245         prvm_edict_t *edict;
7246
7247         // this function draws bounding boxes of server entities
7248         if (!sv.active)
7249                 return;
7250
7251         GL_CullFace(GL_NONE);
7252         R_SetupShader_Generic_NoTexture(false, false);
7253
7254         for (i = 0;i < numsurfaces;i++)
7255         {
7256                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7257                 switch ((int)PRVM_serveredictfloat(edict, solid))
7258                 {
7259                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7260                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7261                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7262                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7263                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7264                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7265                 }
7266                 color[3] *= r_showbboxes.value;
7267                 color[3] = bound(0, color[3], 1);
7268                 GL_DepthTest(!r_showdisabledepthtest.integer);
7269                 GL_CullFace(r_refdef.view.cullface_front);
7270                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7271         }
7272 }
7273
7274 static void R_DrawEntityBBoxes(void)
7275 {
7276         int i;
7277         prvm_edict_t *edict;
7278         vec3_t center;
7279         prvm_prog_t *prog = SVVM_prog;
7280
7281         // this function draws bounding boxes of server entities
7282         if (!sv.active)
7283                 return;
7284
7285         for (i = 0;i < prog->num_edicts;i++)
7286         {
7287                 edict = PRVM_EDICT_NUM(i);
7288                 if (edict->priv.server->free)
7289                         continue;
7290                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7291                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7292                         continue;
7293                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7294                         continue;
7295                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7296                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7297         }
7298 }
7299
7300 static const int nomodelelement3i[24] =
7301 {
7302         5, 2, 0,
7303         5, 1, 2,
7304         5, 0, 3,
7305         5, 3, 1,
7306         0, 2, 4,
7307         2, 1, 4,
7308         3, 0, 4,
7309         1, 3, 4
7310 };
7311
7312 static const unsigned short nomodelelement3s[24] =
7313 {
7314         5, 2, 0,
7315         5, 1, 2,
7316         5, 0, 3,
7317         5, 3, 1,
7318         0, 2, 4,
7319         2, 1, 4,
7320         3, 0, 4,
7321         1, 3, 4
7322 };
7323
7324 static const float nomodelvertex3f[6*3] =
7325 {
7326         -16,   0,   0,
7327          16,   0,   0,
7328           0, -16,   0,
7329           0,  16,   0,
7330           0,   0, -16,
7331           0,   0,  16
7332 };
7333
7334 static const float nomodelcolor4f[6*4] =
7335 {
7336         0.0f, 0.0f, 0.5f, 1.0f,
7337         0.0f, 0.0f, 0.5f, 1.0f,
7338         0.0f, 0.5f, 0.0f, 1.0f,
7339         0.0f, 0.5f, 0.0f, 1.0f,
7340         0.5f, 0.0f, 0.0f, 1.0f,
7341         0.5f, 0.0f, 0.0f, 1.0f
7342 };
7343
7344 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7345 {
7346         int i;
7347         float f1, f2, *c;
7348         float color4f[6*4];
7349
7350         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);
7351
7352         // this is only called once per entity so numsurfaces is always 1, and
7353         // surfacelist is always {0}, so this code does not handle batches
7354
7355         if (rsurface.ent_flags & RENDER_ADDITIVE)
7356         {
7357                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7358                 GL_DepthMask(false);
7359         }
7360         else if (rsurface.colormod[3] < 1)
7361         {
7362                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7363                 GL_DepthMask(false);
7364         }
7365         else
7366         {
7367                 GL_BlendFunc(GL_ONE, GL_ZERO);
7368                 GL_DepthMask(true);
7369         }
7370         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7371         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7372         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7373         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7374         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7375         for (i = 0, c = color4f;i < 6;i++, c += 4)
7376         {
7377                 c[0] *= rsurface.colormod[0];
7378                 c[1] *= rsurface.colormod[1];
7379                 c[2] *= rsurface.colormod[2];
7380                 c[3] *= rsurface.colormod[3];
7381         }
7382         if (r_refdef.fogenabled)
7383         {
7384                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7385                 {
7386                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7387                         f2 = 1 - f1;
7388                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7389                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7390                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7391                 }
7392         }
7393 //      R_Mesh_ResetTextureState();
7394         R_SetupShader_Generic_NoTexture(false, false);
7395         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7396         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7397 }
7398
7399 void R_DrawNoModel(entity_render_t *ent)
7400 {
7401         vec3_t org;
7402         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7403         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7404                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7405         else
7406                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7407 }
7408
7409 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7410 {
7411         vec3_t right1, right2, diff, normal;
7412
7413         VectorSubtract (org2, org1, normal);
7414
7415         // calculate 'right' vector for start
7416         VectorSubtract (r_refdef.view.origin, org1, diff);
7417         CrossProduct (normal, diff, right1);
7418         VectorNormalize (right1);
7419
7420         // calculate 'right' vector for end
7421         VectorSubtract (r_refdef.view.origin, org2, diff);
7422         CrossProduct (normal, diff, right2);
7423         VectorNormalize (right2);
7424
7425         vert[ 0] = org1[0] + width * right1[0];
7426         vert[ 1] = org1[1] + width * right1[1];
7427         vert[ 2] = org1[2] + width * right1[2];
7428         vert[ 3] = org1[0] - width * right1[0];
7429         vert[ 4] = org1[1] - width * right1[1];
7430         vert[ 5] = org1[2] - width * right1[2];
7431         vert[ 6] = org2[0] - width * right2[0];
7432         vert[ 7] = org2[1] - width * right2[1];
7433         vert[ 8] = org2[2] - width * right2[2];
7434         vert[ 9] = org2[0] + width * right2[0];
7435         vert[10] = org2[1] + width * right2[1];
7436         vert[11] = org2[2] + width * right2[2];
7437 }
7438
7439 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)
7440 {
7441         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7442         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7443         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7444         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7445         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7446         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7447         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7448         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7449         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7450         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7451         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7452         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7453 }
7454
7455 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7456 {
7457         int i;
7458         float *vertex3f;
7459         float v[3];
7460         VectorSet(v, x, y, z);
7461         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7462                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7463                         break;
7464         if (i == mesh->numvertices)
7465         {
7466                 if (mesh->numvertices < mesh->maxvertices)
7467                 {
7468                         VectorCopy(v, vertex3f);
7469                         mesh->numvertices++;
7470                 }
7471                 return mesh->numvertices;
7472         }
7473         else
7474                 return i;
7475 }
7476
7477 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7478 {
7479         int i;
7480         int *e, element[3];
7481         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7482         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7483         e = mesh->element3i + mesh->numtriangles * 3;
7484         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7485         {
7486                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7487                 if (mesh->numtriangles < mesh->maxtriangles)
7488                 {
7489                         *e++ = element[0];
7490                         *e++ = element[1];
7491                         *e++ = element[2];
7492                         mesh->numtriangles++;
7493                 }
7494                 element[1] = element[2];
7495         }
7496 }
7497
7498 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7499 {
7500         int i;
7501         int *e, element[3];
7502         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7503         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7504         e = mesh->element3i + mesh->numtriangles * 3;
7505         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7506         {
7507                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7508                 if (mesh->numtriangles < mesh->maxtriangles)
7509                 {
7510                         *e++ = element[0];
7511                         *e++ = element[1];
7512                         *e++ = element[2];
7513                         mesh->numtriangles++;
7514                 }
7515                 element[1] = element[2];
7516         }
7517 }
7518
7519 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7520 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7521 {
7522         int planenum, planenum2;
7523         int w;
7524         int tempnumpoints;
7525         mplane_t *plane, *plane2;
7526         double maxdist;
7527         double temppoints[2][256*3];
7528         // figure out how large a bounding box we need to properly compute this brush
7529         maxdist = 0;
7530         for (w = 0;w < numplanes;w++)
7531                 maxdist = max(maxdist, fabs(planes[w].dist));
7532         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7533         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7534         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7535         {
7536                 w = 0;
7537                 tempnumpoints = 4;
7538                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7539                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7540                 {
7541                         if (planenum2 == planenum)
7542                                 continue;
7543                         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);
7544                         w = !w;
7545                 }
7546                 if (tempnumpoints < 3)
7547                         continue;
7548                 // generate elements forming a triangle fan for this polygon
7549                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7550         }
7551 }
7552
7553 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)
7554 {
7555         texturelayer_t *layer;
7556         layer = t->currentlayers + t->currentnumlayers++;
7557         layer->type = type;
7558         layer->depthmask = depthmask;
7559         layer->blendfunc1 = blendfunc1;
7560         layer->blendfunc2 = blendfunc2;
7561         layer->texture = texture;
7562         layer->texmatrix = *matrix;
7563         layer->color[0] = r;
7564         layer->color[1] = g;
7565         layer->color[2] = b;
7566         layer->color[3] = a;
7567 }
7568
7569 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7570 {
7571         if(parms[0] == 0 && parms[1] == 0)
7572                 return false;
7573         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7574                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7575                         return false;
7576         return true;
7577 }
7578
7579 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7580 {
7581         double index, f;
7582         index = parms[2] + rsurface.shadertime * parms[3];
7583         index -= floor(index);
7584         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7585         {
7586         default:
7587         case Q3WAVEFUNC_NONE:
7588         case Q3WAVEFUNC_NOISE:
7589         case Q3WAVEFUNC_COUNT:
7590                 f = 0;
7591                 break;
7592         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7593         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7594         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7595         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7596         case Q3WAVEFUNC_TRIANGLE:
7597                 index *= 4;
7598                 f = index - floor(index);
7599                 if (index < 1)
7600                 {
7601                         // f = f;
7602                 }
7603                 else if (index < 2)
7604                         f = 1 - f;
7605                 else if (index < 3)
7606                         f = -f;
7607                 else
7608                         f = -(1 - f);
7609                 break;
7610         }
7611         f = parms[0] + parms[1] * f;
7612         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7613                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7614         return (float) f;
7615 }
7616
7617 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7618 {
7619         int w, h, idx;
7620         double f;
7621         double offsetd[2];
7622         float tcmat[12];
7623         matrix4x4_t matrix, temp;
7624         switch(tcmod->tcmod)
7625         {
7626                 case Q3TCMOD_COUNT:
7627                 case Q3TCMOD_NONE:
7628                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7629                                 matrix = r_waterscrollmatrix;
7630                         else
7631                                 matrix = identitymatrix;
7632                         break;
7633                 case Q3TCMOD_ENTITYTRANSLATE:
7634                         // this is used in Q3 to allow the gamecode to control texcoord
7635                         // scrolling on the entity, which is not supported in darkplaces yet.
7636                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7637                         break;
7638                 case Q3TCMOD_ROTATE:
7639                         f = tcmod->parms[0] * rsurface.shadertime;
7640                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7641                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7642                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7643                         break;
7644                 case Q3TCMOD_SCALE:
7645                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7646                         break;
7647                 case Q3TCMOD_SCROLL:
7648                         // extra care is needed because of precision breakdown with large values of time
7649                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7650                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7651                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7652                         break;
7653                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7654                         w = (int) tcmod->parms[0];
7655                         h = (int) tcmod->parms[1];
7656                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7657                         f = f - floor(f);
7658                         idx = (int) floor(f * w * h);
7659                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7660                         break;
7661                 case Q3TCMOD_STRETCH:
7662                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7663                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7664                         break;
7665                 case Q3TCMOD_TRANSFORM:
7666                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7667                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7668                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7669                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7670                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7671                         break;
7672                 case Q3TCMOD_TURBULENT:
7673                         // this is handled in the RSurf_PrepareVertices function
7674                         matrix = identitymatrix;
7675                         break;
7676         }
7677         temp = *texmatrix;
7678         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7679 }
7680
7681 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7682 {
7683         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7684         char name[MAX_QPATH];
7685         skinframe_t *skinframe;
7686         unsigned char pixels[296*194];
7687         strlcpy(cache->name, skinname, sizeof(cache->name));
7688         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7689         if (developer_loading.integer)
7690                 Con_Printf("loading %s\n", name);
7691         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7692         if (!skinframe || !skinframe->base)
7693         {
7694                 unsigned char *f;
7695                 fs_offset_t filesize;
7696                 skinframe = NULL;
7697                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7698                 if (f)
7699                 {
7700                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7701                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7702                         Mem_Free(f);
7703                 }
7704         }
7705         cache->skinframe = skinframe;
7706 }
7707
7708 texture_t *R_GetCurrentTexture(texture_t *t)
7709 {
7710         int i;
7711         const entity_render_t *ent = rsurface.entity;
7712         dp_model_t *model = ent->model;
7713         q3shaderinfo_layer_tcmod_t *tcmod;
7714
7715         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7716                 return t->currentframe;
7717         t->update_lastrenderframe = r_textureframe;
7718         t->update_lastrenderentity = (void *)ent;
7719
7720         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7721                 t->camera_entity = ent->entitynumber;
7722         else
7723                 t->camera_entity = 0;
7724
7725         // switch to an alternate material if this is a q1bsp animated material
7726         {
7727                 texture_t *texture = t;
7728                 int s = rsurface.ent_skinnum;
7729                 if ((unsigned int)s >= (unsigned int)model->numskins)
7730                         s = 0;
7731                 if (model->skinscenes)
7732                 {
7733                         if (model->skinscenes[s].framecount > 1)
7734                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7735                         else
7736                                 s = model->skinscenes[s].firstframe;
7737                 }
7738                 if (s > 0)
7739                         t = t + s * model->num_surfaces;
7740                 if (t->animated)
7741                 {
7742                         // use an alternate animation if the entity's frame is not 0,
7743                         // and only if the texture has an alternate animation
7744                         if (rsurface.ent_alttextures && t->anim_total[1])
7745                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7746                         else
7747                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7748                 }
7749                 texture->currentframe = t;
7750         }
7751
7752         // update currentskinframe to be a qw skin or animation frame
7753         if (rsurface.ent_qwskin >= 0)
7754         {
7755                 i = rsurface.ent_qwskin;
7756                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7757                 {
7758                         r_qwskincache_size = cl.maxclients;
7759                         if (r_qwskincache)
7760                                 Mem_Free(r_qwskincache);
7761                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7762                 }
7763                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7764                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7765                 t->currentskinframe = r_qwskincache[i].skinframe;
7766                 if (t->currentskinframe == NULL)
7767                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7768         }
7769         else if (t->numskinframes >= 2)
7770                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7771         if (t->backgroundnumskinframes >= 2)
7772                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7773
7774         t->currentmaterialflags = t->basematerialflags;
7775         t->currentalpha = rsurface.colormod[3];
7776         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7777                 t->currentalpha *= r_wateralpha.value;
7778         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7779                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7780         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7781                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7782         if (!(rsurface.ent_flags & RENDER_LIGHT))
7783                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7784         else if (FAKELIGHT_ENABLED)
7785         {
7786                 // no modellight if using fakelight for the map
7787         }
7788         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7789         {
7790                 // pick a model lighting mode
7791                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7792                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7793                 else
7794                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7795         }
7796         if (rsurface.ent_flags & RENDER_ADDITIVE)
7797                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7798         else if (t->currentalpha < 1)
7799                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7800         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7801         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7802                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7803         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7804                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7805         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7806                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7807         if (t->backgroundnumskinframes)
7808                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7809         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7810         {
7811                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7812                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7813         }
7814         else
7815                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7816         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7817         {
7818                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7819                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7820         }
7821         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7822                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7823
7824         // there is no tcmod
7825         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7826         {
7827                 t->currenttexmatrix = r_waterscrollmatrix;
7828                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7829         }
7830         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7831         {
7832                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7833                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7834         }
7835
7836         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7837                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7838         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7839                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7840
7841         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7842         if (t->currentskinframe->qpixels)
7843                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7844         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7845         if (!t->basetexture)
7846                 t->basetexture = r_texture_notexture;
7847         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7848         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7849         t->nmaptexture = t->currentskinframe->nmap;
7850         if (!t->nmaptexture)
7851                 t->nmaptexture = r_texture_blanknormalmap;
7852         t->glosstexture = r_texture_black;
7853         t->glowtexture = t->currentskinframe->glow;
7854         t->fogtexture = t->currentskinframe->fog;
7855         t->reflectmasktexture = t->currentskinframe->reflect;
7856         if (t->backgroundnumskinframes)
7857         {
7858                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7859                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7860                 t->backgroundglosstexture = r_texture_black;
7861                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7862                 if (!t->backgroundnmaptexture)
7863                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7864         }
7865         else
7866         {
7867                 t->backgroundbasetexture = r_texture_white;
7868                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7869                 t->backgroundglosstexture = r_texture_black;
7870                 t->backgroundglowtexture = NULL;
7871         }
7872         t->specularpower = r_shadow_glossexponent.value;
7873         // TODO: store reference values for these in the texture?
7874         t->specularscale = 0;
7875         if (r_shadow_gloss.integer > 0)
7876         {
7877                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7878                 {
7879                         if (r_shadow_glossintensity.value > 0)
7880                         {
7881                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7882                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7883                                 t->specularscale = r_shadow_glossintensity.value;
7884                         }
7885                 }
7886                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7887                 {
7888                         t->glosstexture = r_texture_white;
7889                         t->backgroundglosstexture = r_texture_white;
7890                         t->specularscale = r_shadow_gloss2intensity.value;
7891                         t->specularpower = r_shadow_gloss2exponent.value;
7892                 }
7893         }
7894         t->specularscale *= t->specularscalemod;
7895         t->specularpower *= t->specularpowermod;
7896         t->rtlightambient = 0;
7897
7898         // lightmaps mode looks bad with dlights using actual texturing, so turn
7899         // off the colormap and glossmap, but leave the normalmap on as it still
7900         // accurately represents the shading involved
7901         if (gl_lightmaps.integer)
7902         {
7903                 t->basetexture = r_texture_grey128;
7904                 t->pantstexture = r_texture_black;
7905                 t->shirttexture = r_texture_black;
7906                 t->nmaptexture = r_texture_blanknormalmap;
7907                 t->glosstexture = r_texture_black;
7908                 t->glowtexture = NULL;
7909                 t->fogtexture = NULL;
7910                 t->reflectmasktexture = NULL;
7911                 t->backgroundbasetexture = NULL;
7912                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7913                 t->backgroundglosstexture = r_texture_black;
7914                 t->backgroundglowtexture = NULL;
7915                 t->specularscale = 0;
7916                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7917         }
7918
7919         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7920         VectorClear(t->dlightcolor);
7921         t->currentnumlayers = 0;
7922         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7923         {
7924                 int blendfunc1, blendfunc2;
7925                 qboolean depthmask;
7926                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7927                 {
7928                         blendfunc1 = GL_SRC_ALPHA;
7929                         blendfunc2 = GL_ONE;
7930                 }
7931                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7932                 {
7933                         blendfunc1 = GL_SRC_ALPHA;
7934                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7935                 }
7936                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7937                 {
7938                         blendfunc1 = t->customblendfunc[0];
7939                         blendfunc2 = t->customblendfunc[1];
7940                 }
7941                 else
7942                 {
7943                         blendfunc1 = GL_ONE;
7944                         blendfunc2 = GL_ZERO;
7945                 }
7946                 // don't colormod evilblend textures
7947                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7948                         VectorSet(t->lightmapcolor, 1, 1, 1);
7949                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7950                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7951                 {
7952                         // fullbright is not affected by r_refdef.lightmapintensity
7953                         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]);
7954                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7955                                 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]);
7956                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7957                                 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]);
7958                 }
7959                 else
7960                 {
7961                         vec3_t ambientcolor;
7962                         float colorscale;
7963                         // set the color tint used for lights affecting this surface
7964                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7965                         colorscale = 2;
7966                         // q3bsp has no lightmap updates, so the lightstylevalue that
7967                         // would normally be baked into the lightmap must be
7968                         // applied to the color
7969                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7970                         if (model->type == mod_brushq3)
7971                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7972                         colorscale *= r_refdef.lightmapintensity;
7973                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7974                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7975                         // basic lit geometry
7976                         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]);
7977                         // add pants/shirt if needed
7978                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7979                                 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]);
7980                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7981                                 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]);
7982                         // now add ambient passes if needed
7983                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7984                         {
7985                                 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]);
7986                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7987                                         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]);
7988                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7989                                         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]);
7990                         }
7991                 }
7992                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7993                         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]);
7994                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7995                 {
7996                         // if this is opaque use alpha blend which will darken the earlier
7997                         // passes cheaply.
7998                         //
7999                         // if this is an alpha blended material, all the earlier passes
8000                         // were darkened by fog already, so we only need to add the fog
8001                         // color ontop through the fog mask texture
8002                         //
8003                         // if this is an additive blended material, all the earlier passes
8004                         // were darkened by fog already, and we should not add fog color
8005                         // (because the background was not darkened, there is no fog color
8006                         // that was lost behind it).
8007                         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]);
8008                 }
8009         }
8010
8011         return t->currentframe;
8012 }
8013
8014 rsurfacestate_t rsurface;
8015
8016 void RSurf_ActiveWorldEntity(void)
8017 {
8018         dp_model_t *model = r_refdef.scene.worldmodel;
8019         //if (rsurface.entity == r_refdef.scene.worldentity)
8020         //      return;
8021         rsurface.entity = r_refdef.scene.worldentity;
8022         rsurface.skeleton = NULL;
8023         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8024         rsurface.ent_skinnum = 0;
8025         rsurface.ent_qwskin = -1;
8026         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8027         rsurface.shadertime = r_refdef.scene.time;
8028         rsurface.matrix = identitymatrix;
8029         rsurface.inversematrix = identitymatrix;
8030         rsurface.matrixscale = 1;
8031         rsurface.inversematrixscale = 1;
8032         R_EntityMatrix(&identitymatrix);
8033         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8034         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8035         rsurface.fograngerecip = r_refdef.fograngerecip;
8036         rsurface.fogheightfade = r_refdef.fogheightfade;
8037         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8038         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8039         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8040         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8041         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8042         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8043         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8044         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8045         rsurface.colormod[3] = 1;
8046         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);
8047         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8048         rsurface.frameblend[0].lerp = 1;
8049         rsurface.ent_alttextures = false;
8050         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8051         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8052         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8053         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8054         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8055         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8056         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8057         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8058         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8059         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8060         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8061         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8062         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8063         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8064         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8065         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8067         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8068         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8070         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8071         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8072         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8073         rsurface.modelelement3i = model->surfmesh.data_element3i;
8074         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8075         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8076         rsurface.modelelement3s = model->surfmesh.data_element3s;
8077         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8078         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8079         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8080         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8081         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8082         rsurface.modelsurfaces = model->data_surfaces;
8083         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8084         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8085         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8086         rsurface.modelgeneratedvertex = false;
8087         rsurface.batchgeneratedvertex = false;
8088         rsurface.batchfirstvertex = 0;
8089         rsurface.batchnumvertices = 0;
8090         rsurface.batchfirsttriangle = 0;
8091         rsurface.batchnumtriangles = 0;
8092         rsurface.batchvertex3f  = NULL;
8093         rsurface.batchvertex3f_vertexbuffer = NULL;
8094         rsurface.batchvertex3f_bufferoffset = 0;
8095         rsurface.batchsvector3f = NULL;
8096         rsurface.batchsvector3f_vertexbuffer = NULL;
8097         rsurface.batchsvector3f_bufferoffset = 0;
8098         rsurface.batchtvector3f = NULL;
8099         rsurface.batchtvector3f_vertexbuffer = NULL;
8100         rsurface.batchtvector3f_bufferoffset = 0;
8101         rsurface.batchnormal3f  = NULL;
8102         rsurface.batchnormal3f_vertexbuffer = NULL;
8103         rsurface.batchnormal3f_bufferoffset = 0;
8104         rsurface.batchlightmapcolor4f = NULL;
8105         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8106         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8107         rsurface.batchtexcoordtexture2f = NULL;
8108         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8109         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8110         rsurface.batchtexcoordlightmap2f = NULL;
8111         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8112         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8113         rsurface.batchvertexmesh = NULL;
8114         rsurface.batchvertexmeshbuffer = NULL;
8115         rsurface.batchvertex3fbuffer = NULL;
8116         rsurface.batchelement3i = NULL;
8117         rsurface.batchelement3i_indexbuffer = NULL;
8118         rsurface.batchelement3i_bufferoffset = 0;
8119         rsurface.batchelement3s = NULL;
8120         rsurface.batchelement3s_indexbuffer = NULL;
8121         rsurface.batchelement3s_bufferoffset = 0;
8122         rsurface.passcolor4f = NULL;
8123         rsurface.passcolor4f_vertexbuffer = NULL;
8124         rsurface.passcolor4f_bufferoffset = 0;
8125 }
8126
8127 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8128 {
8129         dp_model_t *model = ent->model;
8130         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8131         //      return;
8132         rsurface.entity = (entity_render_t *)ent;
8133         rsurface.skeleton = ent->skeleton;
8134         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8135         rsurface.ent_skinnum = ent->skinnum;
8136         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;
8137         rsurface.ent_flags = ent->flags;
8138         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8139         rsurface.matrix = ent->matrix;
8140         rsurface.inversematrix = ent->inversematrix;
8141         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8142         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8143         R_EntityMatrix(&rsurface.matrix);
8144         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8145         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8146         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8147         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8148         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8149         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8150         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8151         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8152         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8153         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8154         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8155         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8156         rsurface.colormod[3] = ent->alpha;
8157         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8158         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8159         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8160         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8161         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8162         if (ent->model->brush.submodel && !prepass)
8163         {
8164                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8165                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8166         }
8167         if (model->surfmesh.isanimated && model->AnimateVertices)
8168         {
8169                 if (ent->animcache_vertex3f)
8170                 {
8171                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8172                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8173                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8174                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8175                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8176                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8177                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8178                 }
8179                 else if (wanttangents)
8180                 {
8181                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8182                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8183                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8184                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8185                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8186                         rsurface.modelvertexmesh = NULL;
8187                         rsurface.modelvertexmeshbuffer = NULL;
8188                         rsurface.modelvertex3fbuffer = NULL;
8189                 }
8190                 else if (wantnormals)
8191                 {
8192                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8193                         rsurface.modelsvector3f = NULL;
8194                         rsurface.modeltvector3f = NULL;
8195                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8196                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8197                         rsurface.modelvertexmesh = NULL;
8198                         rsurface.modelvertexmeshbuffer = NULL;
8199                         rsurface.modelvertex3fbuffer = NULL;
8200                 }
8201                 else
8202                 {
8203                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8204                         rsurface.modelsvector3f = NULL;
8205                         rsurface.modeltvector3f = NULL;
8206                         rsurface.modelnormal3f = NULL;
8207                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8208                         rsurface.modelvertexmesh = NULL;
8209                         rsurface.modelvertexmeshbuffer = NULL;
8210                         rsurface.modelvertex3fbuffer = NULL;
8211                 }
8212                 rsurface.modelvertex3f_vertexbuffer = 0;
8213                 rsurface.modelvertex3f_bufferoffset = 0;
8214                 rsurface.modelsvector3f_vertexbuffer = 0;
8215                 rsurface.modelsvector3f_bufferoffset = 0;
8216                 rsurface.modeltvector3f_vertexbuffer = 0;
8217                 rsurface.modeltvector3f_bufferoffset = 0;
8218                 rsurface.modelnormal3f_vertexbuffer = 0;
8219                 rsurface.modelnormal3f_bufferoffset = 0;
8220                 rsurface.modelgeneratedvertex = true;
8221         }
8222         else
8223         {
8224                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8225                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8226                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8227                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8228                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8229                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8230                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8231                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8232                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8233                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8234                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8235                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8236                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8237                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8238                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8239                 rsurface.modelgeneratedvertex = false;
8240         }
8241         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8242         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8243         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8244         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8245         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8246         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8247         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8248         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8250         rsurface.modelelement3i = model->surfmesh.data_element3i;
8251         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8252         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8253         rsurface.modelelement3s = model->surfmesh.data_element3s;
8254         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8255         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8256         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8257         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8258         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8259         rsurface.modelsurfaces = model->data_surfaces;
8260         rsurface.batchgeneratedvertex = false;
8261         rsurface.batchfirstvertex = 0;
8262         rsurface.batchnumvertices = 0;
8263         rsurface.batchfirsttriangle = 0;
8264         rsurface.batchnumtriangles = 0;
8265         rsurface.batchvertex3f  = NULL;
8266         rsurface.batchvertex3f_vertexbuffer = NULL;
8267         rsurface.batchvertex3f_bufferoffset = 0;
8268         rsurface.batchsvector3f = NULL;
8269         rsurface.batchsvector3f_vertexbuffer = NULL;
8270         rsurface.batchsvector3f_bufferoffset = 0;
8271         rsurface.batchtvector3f = NULL;
8272         rsurface.batchtvector3f_vertexbuffer = NULL;
8273         rsurface.batchtvector3f_bufferoffset = 0;
8274         rsurface.batchnormal3f  = NULL;
8275         rsurface.batchnormal3f_vertexbuffer = NULL;
8276         rsurface.batchnormal3f_bufferoffset = 0;
8277         rsurface.batchlightmapcolor4f = NULL;
8278         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8279         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8280         rsurface.batchtexcoordtexture2f = NULL;
8281         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8282         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8283         rsurface.batchtexcoordlightmap2f = NULL;
8284         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8285         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8286         rsurface.batchvertexmesh = NULL;
8287         rsurface.batchvertexmeshbuffer = NULL;
8288         rsurface.batchvertex3fbuffer = NULL;
8289         rsurface.batchelement3i = NULL;
8290         rsurface.batchelement3i_indexbuffer = NULL;
8291         rsurface.batchelement3i_bufferoffset = 0;
8292         rsurface.batchelement3s = NULL;
8293         rsurface.batchelement3s_indexbuffer = NULL;
8294         rsurface.batchelement3s_bufferoffset = 0;
8295         rsurface.passcolor4f = NULL;
8296         rsurface.passcolor4f_vertexbuffer = NULL;
8297         rsurface.passcolor4f_bufferoffset = 0;
8298 }
8299
8300 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)
8301 {
8302         rsurface.entity = r_refdef.scene.worldentity;
8303         rsurface.skeleton = NULL;
8304         rsurface.ent_skinnum = 0;
8305         rsurface.ent_qwskin = -1;
8306         rsurface.ent_flags = entflags;
8307         rsurface.shadertime = r_refdef.scene.time - shadertime;
8308         rsurface.modelnumvertices = numvertices;
8309         rsurface.modelnumtriangles = numtriangles;
8310         rsurface.matrix = *matrix;
8311         rsurface.inversematrix = *inversematrix;
8312         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8313         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8314         R_EntityMatrix(&rsurface.matrix);
8315         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8316         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8317         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8318         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8319         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8320         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8321         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8322         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8323         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8324         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8325         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8326         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8327         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);
8328         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8329         rsurface.frameblend[0].lerp = 1;
8330         rsurface.ent_alttextures = false;
8331         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8332         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8333         if (wanttangents)
8334         {
8335                 rsurface.modelvertex3f = (float *)vertex3f;
8336                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8337                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8338                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8339         }
8340         else if (wantnormals)
8341         {
8342                 rsurface.modelvertex3f = (float *)vertex3f;
8343                 rsurface.modelsvector3f = NULL;
8344                 rsurface.modeltvector3f = NULL;
8345                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8346         }
8347         else
8348         {
8349                 rsurface.modelvertex3f = (float *)vertex3f;
8350                 rsurface.modelsvector3f = NULL;
8351                 rsurface.modeltvector3f = NULL;
8352                 rsurface.modelnormal3f = NULL;
8353         }
8354         rsurface.modelvertexmesh = NULL;
8355         rsurface.modelvertexmeshbuffer = NULL;
8356         rsurface.modelvertex3fbuffer = NULL;
8357         rsurface.modelvertex3f_vertexbuffer = 0;
8358         rsurface.modelvertex3f_bufferoffset = 0;
8359         rsurface.modelsvector3f_vertexbuffer = 0;
8360         rsurface.modelsvector3f_bufferoffset = 0;
8361         rsurface.modeltvector3f_vertexbuffer = 0;
8362         rsurface.modeltvector3f_bufferoffset = 0;
8363         rsurface.modelnormal3f_vertexbuffer = 0;
8364         rsurface.modelnormal3f_bufferoffset = 0;
8365         rsurface.modelgeneratedvertex = true;
8366         rsurface.modellightmapcolor4f  = (float *)color4f;
8367         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8368         rsurface.modellightmapcolor4f_bufferoffset = 0;
8369         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8370         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8371         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8372         rsurface.modeltexcoordlightmap2f  = NULL;
8373         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8374         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8375         rsurface.modelelement3i = (int *)element3i;
8376         rsurface.modelelement3i_indexbuffer = NULL;
8377         rsurface.modelelement3i_bufferoffset = 0;
8378         rsurface.modelelement3s = (unsigned short *)element3s;
8379         rsurface.modelelement3s_indexbuffer = NULL;
8380         rsurface.modelelement3s_bufferoffset = 0;
8381         rsurface.modellightmapoffsets = NULL;
8382         rsurface.modelsurfaces = NULL;
8383         rsurface.batchgeneratedvertex = false;
8384         rsurface.batchfirstvertex = 0;
8385         rsurface.batchnumvertices = 0;
8386         rsurface.batchfirsttriangle = 0;
8387         rsurface.batchnumtriangles = 0;
8388         rsurface.batchvertex3f  = NULL;
8389         rsurface.batchvertex3f_vertexbuffer = NULL;
8390         rsurface.batchvertex3f_bufferoffset = 0;
8391         rsurface.batchsvector3f = NULL;
8392         rsurface.batchsvector3f_vertexbuffer = NULL;
8393         rsurface.batchsvector3f_bufferoffset = 0;
8394         rsurface.batchtvector3f = NULL;
8395         rsurface.batchtvector3f_vertexbuffer = NULL;
8396         rsurface.batchtvector3f_bufferoffset = 0;
8397         rsurface.batchnormal3f  = NULL;
8398         rsurface.batchnormal3f_vertexbuffer = NULL;
8399         rsurface.batchnormal3f_bufferoffset = 0;
8400         rsurface.batchlightmapcolor4f = NULL;
8401         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8402         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8403         rsurface.batchtexcoordtexture2f = NULL;
8404         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8405         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8406         rsurface.batchtexcoordlightmap2f = NULL;
8407         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8408         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8409         rsurface.batchvertexmesh = NULL;
8410         rsurface.batchvertexmeshbuffer = NULL;
8411         rsurface.batchvertex3fbuffer = NULL;
8412         rsurface.batchelement3i = NULL;
8413         rsurface.batchelement3i_indexbuffer = NULL;
8414         rsurface.batchelement3i_bufferoffset = 0;
8415         rsurface.batchelement3s = NULL;
8416         rsurface.batchelement3s_indexbuffer = NULL;
8417         rsurface.batchelement3s_bufferoffset = 0;
8418         rsurface.passcolor4f = NULL;
8419         rsurface.passcolor4f_vertexbuffer = NULL;
8420         rsurface.passcolor4f_bufferoffset = 0;
8421
8422         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8423         {
8424                 if ((wantnormals || wanttangents) && !normal3f)
8425                 {
8426                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8427                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8428                 }
8429                 if (wanttangents && !svector3f)
8430                 {
8431                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8432                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8433                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8434                 }
8435         }
8436 }
8437
8438 float RSurf_FogPoint(const float *v)
8439 {
8440         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8441         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8442         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8443         float FogHeightFade = r_refdef.fogheightfade;
8444         float fogfrac;
8445         unsigned int fogmasktableindex;
8446         if (r_refdef.fogplaneviewabove)
8447                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8448         else
8449                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8450         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8451         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8452 }
8453
8454 float RSurf_FogVertex(const float *v)
8455 {
8456         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8457         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8458         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8459         float FogHeightFade = rsurface.fogheightfade;
8460         float fogfrac;
8461         unsigned int fogmasktableindex;
8462         if (r_refdef.fogplaneviewabove)
8463                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8464         else
8465                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8466         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8467         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8468 }
8469
8470 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8471 {
8472         int i;
8473         for (i = 0;i < numelements;i++)
8474                 outelement3i[i] = inelement3i[i] + adjust;
8475 }
8476
8477 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8478 extern cvar_t gl_vbo;
8479 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8480 {
8481         int deformindex;
8482         int firsttriangle;
8483         int numtriangles;
8484         int firstvertex;
8485         int endvertex;
8486         int numvertices;
8487         int surfacefirsttriangle;
8488         int surfacenumtriangles;
8489         int surfacefirstvertex;
8490         int surfaceendvertex;
8491         int surfacenumvertices;
8492         int batchnumvertices;
8493         int batchnumtriangles;
8494         int needsupdate;
8495         int i, j;
8496         qboolean gaps;
8497         qboolean dynamicvertex;
8498         float amplitude;
8499         float animpos;
8500         float scale;
8501         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8502         float waveparms[4];
8503         q3shaderinfo_deform_t *deform;
8504         const msurface_t *surface, *firstsurface;
8505         r_vertexmesh_t *vertexmesh;
8506         if (!texturenumsurfaces)
8507                 return;
8508         // find vertex range of this surface batch
8509         gaps = false;
8510         firstsurface = texturesurfacelist[0];
8511         firsttriangle = firstsurface->num_firsttriangle;
8512         batchnumvertices = 0;
8513         batchnumtriangles = 0;
8514         firstvertex = endvertex = firstsurface->num_firstvertex;
8515         for (i = 0;i < texturenumsurfaces;i++)
8516         {
8517                 surface = texturesurfacelist[i];
8518                 if (surface != firstsurface + i)
8519                         gaps = true;
8520                 surfacefirstvertex = surface->num_firstvertex;
8521                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8522                 surfacenumvertices = surface->num_vertices;
8523                 surfacenumtriangles = surface->num_triangles;
8524                 if (firstvertex > surfacefirstvertex)
8525                         firstvertex = surfacefirstvertex;
8526                 if (endvertex < surfaceendvertex)
8527                         endvertex = surfaceendvertex;
8528                 batchnumvertices += surfacenumvertices;
8529                 batchnumtriangles += surfacenumtriangles;
8530         }
8531
8532         // we now know the vertex range used, and if there are any gaps in it
8533         rsurface.batchfirstvertex = firstvertex;
8534         rsurface.batchnumvertices = endvertex - firstvertex;
8535         rsurface.batchfirsttriangle = firsttriangle;
8536         rsurface.batchnumtriangles = batchnumtriangles;
8537
8538         // this variable holds flags for which properties have been updated that
8539         // may require regenerating vertexmesh array...
8540         needsupdate = 0;
8541
8542         // check if any dynamic vertex processing must occur
8543         dynamicvertex = false;
8544
8545         // if there is a chance of animated vertex colors, it's a dynamic batch
8546         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8547         {
8548                 dynamicvertex = true;
8549                 batchneed |= BATCHNEED_NOGAPS;
8550                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8551         }
8552
8553         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8554         {
8555                 switch (deform->deform)
8556                 {
8557                 default:
8558                 case Q3DEFORM_PROJECTIONSHADOW:
8559                 case Q3DEFORM_TEXT0:
8560                 case Q3DEFORM_TEXT1:
8561                 case Q3DEFORM_TEXT2:
8562                 case Q3DEFORM_TEXT3:
8563                 case Q3DEFORM_TEXT4:
8564                 case Q3DEFORM_TEXT5:
8565                 case Q3DEFORM_TEXT6:
8566                 case Q3DEFORM_TEXT7:
8567                 case Q3DEFORM_NONE:
8568                         break;
8569                 case Q3DEFORM_AUTOSPRITE:
8570                         dynamicvertex = true;
8571                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8572                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8573                         break;
8574                 case Q3DEFORM_AUTOSPRITE2:
8575                         dynamicvertex = true;
8576                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8577                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8578                         break;
8579                 case Q3DEFORM_NORMAL:
8580                         dynamicvertex = true;
8581                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8582                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8583                         break;
8584                 case Q3DEFORM_WAVE:
8585                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8586                                 break; // if wavefunc is a nop, ignore this transform
8587                         dynamicvertex = true;
8588                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8589                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8590                         break;
8591                 case Q3DEFORM_BULGE:
8592                         dynamicvertex = true;
8593                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8594                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8595                         break;
8596                 case Q3DEFORM_MOVE:
8597                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8598                                 break; // if wavefunc is a nop, ignore this transform
8599                         dynamicvertex = true;
8600                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8601                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8602                         break;
8603                 }
8604         }
8605         switch(rsurface.texture->tcgen.tcgen)
8606         {
8607         default:
8608         case Q3TCGEN_TEXTURE:
8609                 break;
8610         case Q3TCGEN_LIGHTMAP:
8611                 dynamicvertex = true;
8612                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8613                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8614                 break;
8615         case Q3TCGEN_VECTOR:
8616                 dynamicvertex = true;
8617                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8618                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8619                 break;
8620         case Q3TCGEN_ENVIRONMENT:
8621                 dynamicvertex = true;
8622                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8623                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8624                 break;
8625         }
8626         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8627         {
8628                 dynamicvertex = true;
8629                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8630                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8631         }
8632
8633         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8634         {
8635                 dynamicvertex = true;
8636                 batchneed |= BATCHNEED_NOGAPS;
8637                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8638         }
8639
8640         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8641         {
8642                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8643                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8644                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8645                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8646                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8647                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8648                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8649         }
8650
8651         // when the model data has no vertex buffer (dynamic mesh), we need to
8652         // eliminate gaps
8653         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8654                 batchneed |= BATCHNEED_NOGAPS;
8655
8656         // if needsupdate, we have to do a dynamic vertex batch for sure
8657         if (needsupdate & batchneed)
8658                 dynamicvertex = true;
8659
8660         // see if we need to build vertexmesh from arrays
8661         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8662                 dynamicvertex = true;
8663
8664         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8665         // also some drivers strongly dislike firstvertex
8666         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8667                 dynamicvertex = true;
8668
8669         rsurface.batchvertex3f = rsurface.modelvertex3f;
8670         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8671         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8672         rsurface.batchsvector3f = rsurface.modelsvector3f;
8673         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8674         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8675         rsurface.batchtvector3f = rsurface.modeltvector3f;
8676         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8677         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8678         rsurface.batchnormal3f = rsurface.modelnormal3f;
8679         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8680         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8681         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8682         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8683         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8684         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8685         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8686         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8687         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8688         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8689         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8690         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8691         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8692         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8693         rsurface.batchelement3i = rsurface.modelelement3i;
8694         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8695         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8696         rsurface.batchelement3s = rsurface.modelelement3s;
8697         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8698         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8699
8700         // if any dynamic vertex processing has to occur in software, we copy the
8701         // entire surface list together before processing to rebase the vertices
8702         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8703         //
8704         // if any gaps exist and we do not have a static vertex buffer, we have to
8705         // copy the surface list together to avoid wasting upload bandwidth on the
8706         // vertices in the gaps.
8707         //
8708         // if gaps exist and we have a static vertex buffer, we still have to
8709         // combine the index buffer ranges into one dynamic index buffer.
8710         //
8711         // in all cases we end up with data that can be drawn in one call.
8712
8713         if (!dynamicvertex)
8714         {
8715                 // static vertex data, just set pointers...
8716                 rsurface.batchgeneratedvertex = false;
8717                 // if there are gaps, we want to build a combined index buffer,
8718                 // otherwise use the original static buffer with an appropriate offset
8719                 if (gaps)
8720                 {
8721                         // build a new triangle elements array for this batch
8722                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8723                         rsurface.batchfirsttriangle = 0;
8724                         numtriangles = 0;
8725                         for (i = 0;i < texturenumsurfaces;i++)
8726                         {
8727                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8728                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8729                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8730                                 numtriangles += surfacenumtriangles;
8731                         }
8732                         rsurface.batchelement3i_indexbuffer = NULL;
8733                         rsurface.batchelement3i_bufferoffset = 0;
8734                         rsurface.batchelement3s = NULL;
8735                         rsurface.batchelement3s_indexbuffer = NULL;
8736                         rsurface.batchelement3s_bufferoffset = 0;
8737                         if (endvertex <= 65536)
8738                         {
8739                                 // make a 16bit (unsigned short) index array if possible
8740                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8741                                 for (i = 0;i < numtriangles*3;i++)
8742                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8743                         }
8744                 }
8745                 return;
8746         }
8747
8748         // something needs software processing, do it for real...
8749         // we only directly handle separate array data in this case and then
8750         // generate interleaved data if needed...
8751         rsurface.batchgeneratedvertex = true;
8752
8753         // now copy the vertex data into a combined array and make an index array
8754         // (this is what Quake3 does all the time)
8755         //if (gaps || rsurface.batchfirstvertex)
8756         {
8757                 rsurface.batchvertex3fbuffer = NULL;
8758                 rsurface.batchvertexmesh = NULL;
8759                 rsurface.batchvertexmeshbuffer = NULL;
8760                 rsurface.batchvertex3f = NULL;
8761                 rsurface.batchvertex3f_vertexbuffer = NULL;
8762                 rsurface.batchvertex3f_bufferoffset = 0;
8763                 rsurface.batchsvector3f = NULL;
8764                 rsurface.batchsvector3f_vertexbuffer = NULL;
8765                 rsurface.batchsvector3f_bufferoffset = 0;
8766                 rsurface.batchtvector3f = NULL;
8767                 rsurface.batchtvector3f_vertexbuffer = NULL;
8768                 rsurface.batchtvector3f_bufferoffset = 0;
8769                 rsurface.batchnormal3f = NULL;
8770                 rsurface.batchnormal3f_vertexbuffer = NULL;
8771                 rsurface.batchnormal3f_bufferoffset = 0;
8772                 rsurface.batchlightmapcolor4f = NULL;
8773                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8774                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8775                 rsurface.batchtexcoordtexture2f = NULL;
8776                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8777                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8778                 rsurface.batchtexcoordlightmap2f = NULL;
8779                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8780                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8781                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8782                 rsurface.batchelement3i_indexbuffer = NULL;
8783                 rsurface.batchelement3i_bufferoffset = 0;
8784                 rsurface.batchelement3s = NULL;
8785                 rsurface.batchelement3s_indexbuffer = NULL;
8786                 rsurface.batchelement3s_bufferoffset = 0;
8787                 // we'll only be setting up certain arrays as needed
8788                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8789                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8790                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8791                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8792                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8793                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8795                 {
8796                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8797                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798                 }
8799                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8800                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8801                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8802                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8803                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8804                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8805                 numvertices = 0;
8806                 numtriangles = 0;
8807                 for (i = 0;i < texturenumsurfaces;i++)
8808                 {
8809                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8810                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8811                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8812                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8813                         // copy only the data requested
8814                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8815                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8816                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8817                         {
8818                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8819                                 {
8820                                         if (rsurface.batchvertex3f)
8821                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8822                                         else
8823                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8824                                 }
8825                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8826                                 {
8827                                         if (rsurface.modelnormal3f)
8828                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8829                                         else
8830                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8831                                 }
8832                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8833                                 {
8834                                         if (rsurface.modelsvector3f)
8835                                         {
8836                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8837                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8838                                         }
8839                                         else
8840                                         {
8841                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8842                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8843                                         }
8844                                 }
8845                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8846                                 {
8847                                         if (rsurface.modellightmapcolor4f)
8848                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8849                                         else
8850                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8851                                 }
8852                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8853                                 {
8854                                         if (rsurface.modeltexcoordtexture2f)
8855                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8856                                         else
8857                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8858                                 }
8859                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8860                                 {
8861                                         if (rsurface.modeltexcoordlightmap2f)
8862                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8863                                         else
8864                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8865                                 }
8866                         }
8867                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8868                         numvertices += surfacenumvertices;
8869                         numtriangles += surfacenumtriangles;
8870                 }
8871
8872                 // generate a 16bit index array as well if possible
8873                 // (in general, dynamic batches fit)
8874                 if (numvertices <= 65536)
8875                 {
8876                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8877                         for (i = 0;i < numtriangles*3;i++)
8878                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8879                 }
8880
8881                 // since we've copied everything, the batch now starts at 0
8882                 rsurface.batchfirstvertex = 0;
8883                 rsurface.batchnumvertices = batchnumvertices;
8884                 rsurface.batchfirsttriangle = 0;
8885                 rsurface.batchnumtriangles = batchnumtriangles;
8886         }
8887
8888         // q1bsp surfaces rendered in vertex color mode have to have colors
8889         // calculated based on lightstyles
8890         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8891         {
8892                 // generate color arrays for the surfaces in this list
8893                 int c[4];
8894                 int scale;
8895                 int size3;
8896                 const int *offsets;
8897                 const unsigned char *lm;
8898                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8899                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8900                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8901                 numvertices = 0;
8902                 for (i = 0;i < texturenumsurfaces;i++)
8903                 {
8904                         surface = texturesurfacelist[i];
8905                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8906                         surfacenumvertices = surface->num_vertices;
8907                         if (surface->lightmapinfo->samples)
8908                         {
8909                                 for (j = 0;j < surfacenumvertices;j++)
8910                                 {
8911                                         lm = surface->lightmapinfo->samples + offsets[j];
8912                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8913                                         VectorScale(lm, scale, c);
8914                                         if (surface->lightmapinfo->styles[1] != 255)
8915                                         {
8916                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8917                                                 lm += size3;
8918                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8919                                                 VectorMA(c, scale, lm, c);
8920                                                 if (surface->lightmapinfo->styles[2] != 255)
8921                                                 {
8922                                                         lm += size3;
8923                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8924                                                         VectorMA(c, scale, lm, c);
8925                                                         if (surface->lightmapinfo->styles[3] != 255)
8926                                                         {
8927                                                                 lm += size3;
8928                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8929                                                                 VectorMA(c, scale, lm, c);
8930                                                         }
8931                                                 }
8932                                         }
8933                                         c[0] >>= 7;
8934                                         c[1] >>= 7;
8935                                         c[2] >>= 7;
8936                                         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);
8937                                         numvertices++;
8938                                 }
8939                         }
8940                         else
8941                         {
8942                                 for (j = 0;j < surfacenumvertices;j++)
8943                                 {
8944                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8945                                         numvertices++;
8946                                 }
8947                         }
8948                 }
8949         }
8950
8951         // if vertices are deformed (sprite flares and things in maps, possibly
8952         // water waves, bulges and other deformations), modify the copied vertices
8953         // in place
8954         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8955         {
8956                 switch (deform->deform)
8957                 {
8958                 default:
8959                 case Q3DEFORM_PROJECTIONSHADOW:
8960                 case Q3DEFORM_TEXT0:
8961                 case Q3DEFORM_TEXT1:
8962                 case Q3DEFORM_TEXT2:
8963                 case Q3DEFORM_TEXT3:
8964                 case Q3DEFORM_TEXT4:
8965                 case Q3DEFORM_TEXT5:
8966                 case Q3DEFORM_TEXT6:
8967                 case Q3DEFORM_TEXT7:
8968                 case Q3DEFORM_NONE:
8969                         break;
8970                 case Q3DEFORM_AUTOSPRITE:
8971                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8972                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8973                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8974                         VectorNormalize(newforward);
8975                         VectorNormalize(newright);
8976                         VectorNormalize(newup);
8977 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8978 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8979 //                      rsurface.batchvertex3f_bufferoffset = 0;
8980 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8981 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8982 //                      rsurface.batchsvector3f_bufferoffset = 0;
8983 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8984 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8985 //                      rsurface.batchtvector3f_bufferoffset = 0;
8986 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8987 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8988 //                      rsurface.batchnormal3f_bufferoffset = 0;
8989                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8990                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8991                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8992                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8993                                 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);
8994                         // a single autosprite surface can contain multiple sprites...
8995                         for (j = 0;j < batchnumvertices - 3;j += 4)
8996                         {
8997                                 VectorClear(center);
8998                                 for (i = 0;i < 4;i++)
8999                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9000                                 VectorScale(center, 0.25f, center);
9001                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9002                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9003                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9004                                 for (i = 0;i < 4;i++)
9005                                 {
9006                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9007                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9008                                 }
9009                         }
9010                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9011                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9012                         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);
9013                         break;
9014                 case Q3DEFORM_AUTOSPRITE2:
9015                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9016                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9017                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9018                         VectorNormalize(newforward);
9019                         VectorNormalize(newright);
9020                         VectorNormalize(newup);
9021 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9022 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9023 //                      rsurface.batchvertex3f_bufferoffset = 0;
9024                         {
9025                                 const float *v1, *v2;
9026                                 vec3_t start, end;
9027                                 float f, l;
9028                                 struct
9029                                 {
9030                                         float length2;
9031                                         const float *v1;
9032                                         const float *v2;
9033                                 }
9034                                 shortest[2];
9035                                 memset(shortest, 0, sizeof(shortest));
9036                                 // a single autosprite surface can contain multiple sprites...
9037                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9038                                 {
9039                                         VectorClear(center);
9040                                         for (i = 0;i < 4;i++)
9041                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9042                                         VectorScale(center, 0.25f, center);
9043                                         // find the two shortest edges, then use them to define the
9044                                         // axis vectors for rotating around the central axis
9045                                         for (i = 0;i < 6;i++)
9046                                         {
9047                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9048                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9049                                                 l = VectorDistance2(v1, v2);
9050                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9051                                                 if (v1[2] != v2[2])
9052                                                         l += (1.0f / 1024.0f);
9053                                                 if (shortest[0].length2 > l || i == 0)
9054                                                 {
9055                                                         shortest[1] = shortest[0];
9056                                                         shortest[0].length2 = l;
9057                                                         shortest[0].v1 = v1;
9058                                                         shortest[0].v2 = v2;
9059                                                 }
9060                                                 else if (shortest[1].length2 > l || i == 1)
9061                                                 {
9062                                                         shortest[1].length2 = l;
9063                                                         shortest[1].v1 = v1;
9064                                                         shortest[1].v2 = v2;
9065                                                 }
9066                                         }
9067                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9068                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9069                                         // this calculates the right vector from the shortest edge
9070                                         // and the up vector from the edge midpoints
9071                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9072                                         VectorNormalize(right);
9073                                         VectorSubtract(end, start, up);
9074                                         VectorNormalize(up);
9075                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9076                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9077                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9078                                         VectorNegate(forward, forward);
9079                                         VectorReflect(forward, 0, up, forward);
9080                                         VectorNormalize(forward);
9081                                         CrossProduct(up, forward, newright);
9082                                         VectorNormalize(newright);
9083                                         // rotate the quad around the up axis vector, this is made
9084                                         // especially easy by the fact we know the quad is flat,
9085                                         // so we only have to subtract the center position and
9086                                         // measure distance along the right vector, and then
9087                                         // multiply that by the newright vector and add back the
9088                                         // center position
9089                                         // we also need to subtract the old position to undo the
9090                                         // displacement from the center, which we do with a
9091                                         // DotProduct, the subtraction/addition of center is also
9092                                         // optimized into DotProducts here
9093                                         l = DotProduct(right, center);
9094                                         for (i = 0;i < 4;i++)
9095                                         {
9096                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9097                                                 f = DotProduct(right, v1) - l;
9098                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9099                                         }
9100                                 }
9101                         }
9102                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9103                         {
9104 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9105 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9106 //                              rsurface.batchnormal3f_bufferoffset = 0;
9107                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9108                         }
9109                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9110                         {
9111 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9112 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9113 //                              rsurface.batchsvector3f_bufferoffset = 0;
9114 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9115 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9116 //                              rsurface.batchtvector3f_bufferoffset = 0;
9117                                 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);
9118                         }
9119                         break;
9120                 case Q3DEFORM_NORMAL:
9121                         // deform the normals to make reflections wavey
9122                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9123                         rsurface.batchnormal3f_vertexbuffer = NULL;
9124                         rsurface.batchnormal3f_bufferoffset = 0;
9125                         for (j = 0;j < batchnumvertices;j++)
9126                         {
9127                                 float vertex[3];
9128                                 float *normal = rsurface.batchnormal3f + 3*j;
9129                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9130                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9131                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9132                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9133                                 VectorNormalize(normal);
9134                         }
9135                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9136                         {
9137 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9138 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9139 //                              rsurface.batchsvector3f_bufferoffset = 0;
9140 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9141 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9142 //                              rsurface.batchtvector3f_bufferoffset = 0;
9143                                 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);
9144                         }
9145                         break;
9146                 case Q3DEFORM_WAVE:
9147                         // deform vertex array to make wavey water and flags and such
9148                         waveparms[0] = deform->waveparms[0];
9149                         waveparms[1] = deform->waveparms[1];
9150                         waveparms[2] = deform->waveparms[2];
9151                         waveparms[3] = deform->waveparms[3];
9152                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9153                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9154                         // this is how a divisor of vertex influence on deformation
9155                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9156                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9157 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9158 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9159 //                      rsurface.batchvertex3f_bufferoffset = 0;
9160 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9161 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9162 //                      rsurface.batchnormal3f_bufferoffset = 0;
9163                         for (j = 0;j < batchnumvertices;j++)
9164                         {
9165                                 // if the wavefunc depends on time, evaluate it per-vertex
9166                                 if (waveparms[3])
9167                                 {
9168                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9169                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9170                                 }
9171                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9172                         }
9173                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9174                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9175                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9176                         {
9177 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9178 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9179 //                              rsurface.batchsvector3f_bufferoffset = 0;
9180 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9181 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9182 //                              rsurface.batchtvector3f_bufferoffset = 0;
9183                                 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);
9184                         }
9185                         break;
9186                 case Q3DEFORM_BULGE:
9187                         // deform vertex array to make the surface have moving bulges
9188 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9189 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9190 //                      rsurface.batchvertex3f_bufferoffset = 0;
9191 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9192 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9193 //                      rsurface.batchnormal3f_bufferoffset = 0;
9194                         for (j = 0;j < batchnumvertices;j++)
9195                         {
9196                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9197                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9198                         }
9199                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9200                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9201                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9202                         {
9203 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9204 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9205 //                              rsurface.batchsvector3f_bufferoffset = 0;
9206 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9207 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9208 //                              rsurface.batchtvector3f_bufferoffset = 0;
9209                                 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);
9210                         }
9211                         break;
9212                 case Q3DEFORM_MOVE:
9213                         // deform vertex array
9214                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9215                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9216                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9217                         VectorScale(deform->parms, scale, waveparms);
9218 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9219 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9220 //                      rsurface.batchvertex3f_bufferoffset = 0;
9221                         for (j = 0;j < batchnumvertices;j++)
9222                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9223                         break;
9224                 }
9225         }
9226
9227         // generate texcoords based on the chosen texcoord source
9228         switch(rsurface.texture->tcgen.tcgen)
9229         {
9230         default:
9231         case Q3TCGEN_TEXTURE:
9232                 break;
9233         case Q3TCGEN_LIGHTMAP:
9234 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9235 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9236 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9237                 if (rsurface.batchtexcoordlightmap2f)
9238                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9239                 break;
9240         case Q3TCGEN_VECTOR:
9241 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9242 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9243 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9244                 for (j = 0;j < batchnumvertices;j++)
9245                 {
9246                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9247                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9248                 }
9249                 break;
9250         case Q3TCGEN_ENVIRONMENT:
9251                 // make environment reflections using a spheremap
9252                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9253                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9254                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9255                 for (j = 0;j < batchnumvertices;j++)
9256                 {
9257                         // identical to Q3A's method, but executed in worldspace so
9258                         // carried models can be shiny too
9259
9260                         float viewer[3], d, reflected[3], worldreflected[3];
9261
9262                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9263                         // VectorNormalize(viewer);
9264
9265                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9266
9267                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9268                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9269                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9270                         // note: this is proportinal to viewer, so we can normalize later
9271
9272                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9273                         VectorNormalize(worldreflected);
9274
9275                         // note: this sphere map only uses world x and z!
9276                         // so positive and negative y will LOOK THE SAME.
9277                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9278                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9279                 }
9280                 break;
9281         }
9282         // the only tcmod that needs software vertex processing is turbulent, so
9283         // check for it here and apply the changes if needed
9284         // and we only support that as the first one
9285         // (handling a mixture of turbulent and other tcmods would be problematic
9286         //  without punting it entirely to a software path)
9287         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9288         {
9289                 amplitude = rsurface.texture->tcmods[0].parms[1];
9290                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9291 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9292 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9293 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9294                 for (j = 0;j < batchnumvertices;j++)
9295                 {
9296                         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);
9297                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9298                 }
9299         }
9300
9301         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9302         {
9303                 // convert the modified arrays to vertex structs
9304 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9305 //              rsurface.batchvertexmeshbuffer = NULL;
9306                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9307                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9308                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9309                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9310                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9311                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9312                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9313                 {
9314                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9315                         {
9316                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9317                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9318                         }
9319                 }
9320                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9321                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9322                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9323                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9324                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9325                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9326                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9327                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9328                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9329         }
9330 }
9331
9332 void RSurf_DrawBatch(void)
9333 {
9334         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9335         // through the pipeline, killing it earlier in the pipeline would have
9336         // per-surface overhead rather than per-batch overhead, so it's best to
9337         // reject it here, before it hits glDraw.
9338         if (rsurface.batchnumtriangles == 0)
9339                 return;
9340 #if 0
9341         // batch debugging code
9342         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9343         {
9344                 int i;
9345                 int j;
9346                 int c;
9347                 const int *e;
9348                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9349                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9350                 {
9351                         c = e[i];
9352                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9353                         {
9354                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9355                                 {
9356                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9357                                                 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);
9358                                         break;
9359                                 }
9360                         }
9361                 }
9362         }
9363 #endif
9364         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);
9365 }
9366
9367 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9368 {
9369         // pick the closest matching water plane
9370         int planeindex, vertexindex, bestplaneindex = -1;
9371         float d, bestd;
9372         vec3_t vert;
9373         const float *v;
9374         r_waterstate_waterplane_t *p;
9375         qboolean prepared = false;
9376         bestd = 0;
9377         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9378         {
9379                 if(p->camera_entity != rsurface.texture->camera_entity)
9380                         continue;
9381                 d = 0;
9382                 if(!prepared)
9383                 {
9384                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9385                         prepared = true;
9386                         if(rsurface.batchnumvertices == 0)
9387                                 break;
9388                 }
9389                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9390                 {
9391                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9392                         d += fabs(PlaneDiff(vert, &p->plane));
9393                 }
9394                 if (bestd > d || bestplaneindex < 0)
9395                 {
9396                         bestd = d;
9397                         bestplaneindex = planeindex;
9398                 }
9399         }
9400         return bestplaneindex;
9401         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9402         // this situation though, as it might be better to render single larger
9403         // batches with useless stuff (backface culled for example) than to
9404         // render multiple smaller batches
9405 }
9406
9407 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9408 {
9409         int i;
9410         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9411         rsurface.passcolor4f_vertexbuffer = 0;
9412         rsurface.passcolor4f_bufferoffset = 0;
9413         for (i = 0;i < rsurface.batchnumvertices;i++)
9414                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9415 }
9416
9417 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9418 {
9419         int i;
9420         float f;
9421         const float *v;
9422         const float *c;
9423         float *c2;
9424         if (rsurface.passcolor4f)
9425         {
9426                 // generate color arrays
9427                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9428                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9429                 rsurface.passcolor4f_vertexbuffer = 0;
9430                 rsurface.passcolor4f_bufferoffset = 0;
9431                 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)
9432                 {
9433                         f = RSurf_FogVertex(v);
9434                         c2[0] = c[0] * f;
9435                         c2[1] = c[1] * f;
9436                         c2[2] = c[2] * f;
9437                         c2[3] = c[3];
9438                 }
9439         }
9440         else
9441         {
9442                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9443                 rsurface.passcolor4f_vertexbuffer = 0;
9444                 rsurface.passcolor4f_bufferoffset = 0;
9445                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9446                 {
9447                         f = RSurf_FogVertex(v);
9448                         c2[0] = f;
9449                         c2[1] = f;
9450                         c2[2] = f;
9451                         c2[3] = 1;
9452                 }
9453         }
9454 }
9455
9456 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9457 {
9458         int i;
9459         float f;
9460         const float *v;
9461         const float *c;
9462         float *c2;
9463         if (!rsurface.passcolor4f)
9464                 return;
9465         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9466         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9467         rsurface.passcolor4f_vertexbuffer = 0;
9468         rsurface.passcolor4f_bufferoffset = 0;
9469         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)
9470         {
9471                 f = RSurf_FogVertex(v);
9472                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9473                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9474                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9475                 c2[3] = c[3];
9476         }
9477 }
9478
9479 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9480 {
9481         int i;
9482         const float *c;
9483         float *c2;
9484         if (!rsurface.passcolor4f)
9485                 return;
9486         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9487         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9488         rsurface.passcolor4f_vertexbuffer = 0;
9489         rsurface.passcolor4f_bufferoffset = 0;
9490         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9491         {
9492                 c2[0] = c[0] * r;
9493                 c2[1] = c[1] * g;
9494                 c2[2] = c[2] * b;
9495                 c2[3] = c[3] * a;
9496         }
9497 }
9498
9499 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9500 {
9501         int i;
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, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9511         {
9512                 c2[0] = c[0] + r_refdef.scene.ambient;
9513                 c2[1] = c[1] + r_refdef.scene.ambient;
9514                 c2[2] = c[2] + r_refdef.scene.ambient;
9515                 c2[3] = c[3];
9516         }
9517 }
9518
9519 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9520 {
9521         // TODO: optimize
9522         rsurface.passcolor4f = NULL;
9523         rsurface.passcolor4f_vertexbuffer = 0;
9524         rsurface.passcolor4f_bufferoffset = 0;
9525         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9526         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9527         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9528         GL_Color(r, g, b, a);
9529         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9530         RSurf_DrawBatch();
9531 }
9532
9533 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9534 {
9535         // TODO: optimize applyfog && applycolor case
9536         // just apply fog if necessary, and tint the fog color array if necessary
9537         rsurface.passcolor4f = NULL;
9538         rsurface.passcolor4f_vertexbuffer = 0;
9539         rsurface.passcolor4f_bufferoffset = 0;
9540         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9541         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9542         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9543         GL_Color(r, g, b, a);
9544         RSurf_DrawBatch();
9545 }
9546
9547 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9548 {
9549         // TODO: optimize
9550         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9551         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9552         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9553         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9554         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9555         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9556         GL_Color(r, g, b, a);
9557         RSurf_DrawBatch();
9558 }
9559
9560 static void RSurf_DrawBatch_GL11_ClampColor(void)
9561 {
9562         int i;
9563         const float *c1;
9564         float *c2;
9565         if (!rsurface.passcolor4f)
9566                 return;
9567         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9568         {
9569                 c2[0] = bound(0.0f, c1[0], 1.0f);
9570                 c2[1] = bound(0.0f, c1[1], 1.0f);
9571                 c2[2] = bound(0.0f, c1[2], 1.0f);
9572                 c2[3] = bound(0.0f, c1[3], 1.0f);
9573         }
9574 }
9575
9576 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9577 {
9578         int i;
9579         float f;
9580         const float *v;
9581         const float *n;
9582         float *c;
9583         //vec3_t eyedir;
9584
9585         // fake shading
9586         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9587         rsurface.passcolor4f_vertexbuffer = 0;
9588         rsurface.passcolor4f_bufferoffset = 0;
9589         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)
9590         {
9591                 f = -DotProduct(r_refdef.view.forward, n);
9592                 f = max(0, f);
9593                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9594                 f *= r_refdef.lightmapintensity;
9595                 Vector4Set(c, f, f, f, 1);
9596         }
9597 }
9598
9599 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9600 {
9601         RSurf_DrawBatch_GL11_ApplyFakeLight();
9602         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9603         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9604         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9605         GL_Color(r, g, b, a);
9606         RSurf_DrawBatch();
9607 }
9608
9609 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9610 {
9611         int i;
9612         float f;
9613         float alpha;
9614         const float *v;
9615         const float *n;
9616         float *c;
9617         vec3_t ambientcolor;
9618         vec3_t diffusecolor;
9619         vec3_t lightdir;
9620         // TODO: optimize
9621         // model lighting
9622         VectorCopy(rsurface.modellight_lightdir, lightdir);
9623         f = 0.5f * r_refdef.lightmapintensity;
9624         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9625         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9626         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9627         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9628         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9629         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9630         alpha = *a;
9631         if (VectorLength2(diffusecolor) > 0)
9632         {
9633                 // q3-style directional shading
9634                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9635                 rsurface.passcolor4f_vertexbuffer = 0;
9636                 rsurface.passcolor4f_bufferoffset = 0;
9637                 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)
9638                 {
9639                         if ((f = DotProduct(n, lightdir)) > 0)
9640                                 VectorMA(ambientcolor, f, diffusecolor, c);
9641                         else
9642                                 VectorCopy(ambientcolor, c);
9643                         c[3] = alpha;
9644                 }
9645                 *r = 1;
9646                 *g = 1;
9647                 *b = 1;
9648                 *a = 1;
9649                 *applycolor = false;
9650         }
9651         else
9652         {
9653                 *r = ambientcolor[0];
9654                 *g = ambientcolor[1];
9655                 *b = ambientcolor[2];
9656                 rsurface.passcolor4f = NULL;
9657                 rsurface.passcolor4f_vertexbuffer = 0;
9658                 rsurface.passcolor4f_bufferoffset = 0;
9659         }
9660 }
9661
9662 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9663 {
9664         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9665         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9666         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9667         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9668         GL_Color(r, g, b, a);
9669         RSurf_DrawBatch();
9670 }
9671
9672 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9673 {
9674         int i;
9675         float f;
9676         const float *v;
9677         float *c;
9678
9679         // fake shading
9680         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9681         rsurface.passcolor4f_vertexbuffer = 0;
9682         rsurface.passcolor4f_bufferoffset = 0;
9683
9684         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9685         {
9686                 f = 1 - RSurf_FogVertex(v);
9687                 c[0] = r;
9688                 c[1] = g;
9689                 c[2] = b;
9690                 c[3] = f * a;
9691         }
9692 }
9693
9694 void RSurf_SetupDepthAndCulling(void)
9695 {
9696         // submodels are biased to avoid z-fighting with world surfaces that they
9697         // may be exactly overlapping (avoids z-fighting artifacts on certain
9698         // doors and things in Quake maps)
9699         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9700         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9701         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9702         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9703 }
9704
9705 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9706 {
9707         // transparent sky would be ridiculous
9708         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9709                 return;
9710         R_SetupShader_Generic_NoTexture(false, false);
9711         skyrenderlater = true;
9712         RSurf_SetupDepthAndCulling();
9713         GL_DepthMask(true);
9714         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9715         // skymasking on them, and Quake3 never did sky masking (unlike
9716         // software Quake and software Quake2), so disable the sky masking
9717         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9718         // and skymasking also looks very bad when noclipping outside the
9719         // level, so don't use it then either.
9720         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9721         {
9722                 R_Mesh_ResetTextureState();
9723                 if (skyrendermasked)
9724                 {
9725                         R_SetupShader_DepthOrShadow(false);
9726                         // depth-only (masking)
9727                         GL_ColorMask(0,0,0,0);
9728                         // just to make sure that braindead drivers don't draw
9729                         // anything despite that colormask...
9730                         GL_BlendFunc(GL_ZERO, GL_ONE);
9731                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9732                         if (rsurface.batchvertex3fbuffer)
9733                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9734                         else
9735                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9736                 }
9737                 else
9738                 {
9739                         R_SetupShader_Generic_NoTexture(false, false);
9740                         // fog sky
9741                         GL_BlendFunc(GL_ONE, GL_ZERO);
9742                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9743                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9744                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9745                 }
9746                 RSurf_DrawBatch();
9747                 if (skyrendermasked)
9748                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9749         }
9750         R_Mesh_ResetTextureState();
9751         GL_Color(1, 1, 1, 1);
9752 }
9753
9754 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9755 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9756 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9757 {
9758         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9759                 return;
9760         if (prepass)
9761         {
9762                 // render screenspace normalmap to texture
9763                 GL_DepthMask(true);
9764                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9765                 RSurf_DrawBatch();
9766                 return;
9767         }
9768
9769         // bind lightmap texture
9770
9771         // water/refraction/reflection/camera surfaces have to be handled specially
9772         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9773         {
9774                 int start, end, startplaneindex;
9775                 for (start = 0;start < texturenumsurfaces;start = end)
9776                 {
9777                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9778                         if(startplaneindex < 0)
9779                         {
9780                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9781                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9782                                 end = start + 1;
9783                                 continue;
9784                         }
9785                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9786                                 ;
9787                         // now that we have a batch using the same planeindex, render it
9788                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9789                         {
9790                                 // render water or distortion background
9791                                 GL_DepthMask(true);
9792                                 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);
9793                                 RSurf_DrawBatch();
9794                                 // blend surface on top
9795                                 GL_DepthMask(false);
9796                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9797                                 RSurf_DrawBatch();
9798                         }
9799                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9800                         {
9801                                 // render surface with reflection texture as input
9802                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9803                                 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);
9804                                 RSurf_DrawBatch();
9805                         }
9806                 }
9807                 return;
9808         }
9809
9810         // render surface batch normally
9811         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9812         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);
9813         RSurf_DrawBatch();
9814 }
9815
9816 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9817 {
9818         // OpenGL 1.3 path - anything not completely ancient
9819         qboolean applycolor;
9820         qboolean applyfog;
9821         int layerindex;
9822         const texturelayer_t *layer;
9823         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);
9824         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9825
9826         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9827         {
9828                 vec4_t layercolor;
9829                 int layertexrgbscale;
9830                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9831                 {
9832                         if (layerindex == 0)
9833                                 GL_AlphaTest(true);
9834                         else
9835                         {
9836                                 GL_AlphaTest(false);
9837                                 GL_DepthFunc(GL_EQUAL);
9838                         }
9839                 }
9840                 GL_DepthMask(layer->depthmask && writedepth);
9841                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9842                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9843                 {
9844                         layertexrgbscale = 4;
9845                         VectorScale(layer->color, 0.25f, layercolor);
9846                 }
9847                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9848                 {
9849                         layertexrgbscale = 2;
9850                         VectorScale(layer->color, 0.5f, layercolor);
9851                 }
9852                 else
9853                 {
9854                         layertexrgbscale = 1;
9855                         VectorScale(layer->color, 1.0f, layercolor);
9856                 }
9857                 layercolor[3] = layer->color[3];
9858                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9859                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9860                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9861                 switch (layer->type)
9862                 {
9863                 case TEXTURELAYERTYPE_LITTEXTURE:
9864                         // single-pass lightmapped texture with 2x rgbscale
9865                         R_Mesh_TexBind(0, r_texture_white);
9866                         R_Mesh_TexMatrix(0, NULL);
9867                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9868                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9869                         R_Mesh_TexBind(1, layer->texture);
9870                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9871                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9872                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9873                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9874                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9875                         else if (FAKELIGHT_ENABLED)
9876                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9877                         else if (rsurface.uselightmaptexture)
9878                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9879                         else
9880                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9881                         break;
9882                 case TEXTURELAYERTYPE_TEXTURE:
9883                         // singletexture unlit texture with transparency support
9884                         R_Mesh_TexBind(0, layer->texture);
9885                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9886                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9887                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9888                         R_Mesh_TexBind(1, 0);
9889                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9890                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9891                         break;
9892                 case TEXTURELAYERTYPE_FOG:
9893                         // singletexture fogging
9894                         if (layer->texture)
9895                         {
9896                                 R_Mesh_TexBind(0, layer->texture);
9897                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9898                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9899                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9900                         }
9901                         else
9902                         {
9903                                 R_Mesh_TexBind(0, 0);
9904                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9905                         }
9906                         R_Mesh_TexBind(1, 0);
9907                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9908                         // generate a color array for the fog pass
9909                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9910                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9911                         RSurf_DrawBatch();
9912                         break;
9913                 default:
9914                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9915                 }
9916         }
9917         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9918         {
9919                 GL_DepthFunc(GL_LEQUAL);
9920                 GL_AlphaTest(false);
9921         }
9922 }
9923
9924 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9925 {
9926         // OpenGL 1.1 - crusty old voodoo path
9927         qboolean applyfog;
9928         int layerindex;
9929         const texturelayer_t *layer;
9930         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);
9931         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9932
9933         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9934         {
9935                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9936                 {
9937                         if (layerindex == 0)
9938                                 GL_AlphaTest(true);
9939                         else
9940                         {
9941                                 GL_AlphaTest(false);
9942                                 GL_DepthFunc(GL_EQUAL);
9943                         }
9944                 }
9945                 GL_DepthMask(layer->depthmask && writedepth);
9946                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9947                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9948                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9949                 switch (layer->type)
9950                 {
9951                 case TEXTURELAYERTYPE_LITTEXTURE:
9952                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9953                         {
9954                                 // two-pass lit texture with 2x rgbscale
9955                                 // first the lightmap pass
9956                                 R_Mesh_TexBind(0, r_texture_white);
9957                                 R_Mesh_TexMatrix(0, NULL);
9958                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9959                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9960                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9961                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9962                                 else if (FAKELIGHT_ENABLED)
9963                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9964                                 else if (rsurface.uselightmaptexture)
9965                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9966                                 else
9967                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9968                                 // then apply the texture to it
9969                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9970                                 R_Mesh_TexBind(0, layer->texture);
9971                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9972                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9973                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9974                                 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);
9975                         }
9976                         else
9977                         {
9978                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9979                                 R_Mesh_TexBind(0, layer->texture);
9980                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9981                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9982                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9983                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9984                                         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);
9985                                 else
9986                                         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);
9987                         }
9988                         break;
9989                 case TEXTURELAYERTYPE_TEXTURE:
9990                         // singletexture unlit texture with transparency support
9991                         R_Mesh_TexBind(0, layer->texture);
9992                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9993                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9994                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9995                         RSurf_DrawBatch_GL11_Unlit(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
9996                         break;
9997                 case TEXTURELAYERTYPE_FOG:
9998                         // singletexture fogging
9999                         if (layer->texture)
10000                         {
10001                                 R_Mesh_TexBind(0, layer->texture);
10002                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10003                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10004                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10005                         }
10006                         else
10007                         {
10008                                 R_Mesh_TexBind(0, 0);
10009                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10010                         }
10011                         // generate a color array for the fog pass
10012                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10013                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10014                         RSurf_DrawBatch();
10015                         break;
10016                 default:
10017                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10018                 }
10019         }
10020         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10021         {
10022                 GL_DepthFunc(GL_LEQUAL);
10023                 GL_AlphaTest(false);
10024         }
10025 }
10026
10027 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10028 {
10029         int vi;
10030         int j;
10031         r_vertexgeneric_t *batchvertex;
10032         float c[4];
10033
10034 //      R_Mesh_ResetTextureState();
10035         R_SetupShader_Generic_NoTexture(false, false);
10036
10037         if(rsurface.texture && rsurface.texture->currentskinframe)
10038         {
10039                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10040                 c[3] *= rsurface.texture->currentalpha;
10041         }
10042         else
10043         {
10044                 c[0] = 1;
10045                 c[1] = 0;
10046                 c[2] = 1;
10047                 c[3] = 1;
10048         }
10049
10050         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10051         {
10052                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10053                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10054                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10055         }
10056
10057         // brighten it up (as texture value 127 means "unlit")
10058         c[0] *= 2 * r_refdef.view.colorscale;
10059         c[1] *= 2 * r_refdef.view.colorscale;
10060         c[2] *= 2 * r_refdef.view.colorscale;
10061
10062         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10063                 c[3] *= r_wateralpha.value;
10064
10065         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10066         {
10067                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10068                 GL_DepthMask(false);
10069         }
10070         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10071         {
10072                 GL_BlendFunc(GL_ONE, GL_ONE);
10073                 GL_DepthMask(false);
10074         }
10075         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10076         {
10077                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10078                 GL_DepthMask(false);
10079         }
10080         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10081         {
10082                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10083                 GL_DepthMask(false);
10084         }
10085         else
10086         {
10087                 GL_BlendFunc(GL_ONE, GL_ZERO);
10088                 GL_DepthMask(writedepth);
10089         }
10090
10091         if (r_showsurfaces.integer == 3)
10092         {
10093                 rsurface.passcolor4f = NULL;
10094
10095                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10096                 {
10097                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10098
10099                         rsurface.passcolor4f = NULL;
10100                         rsurface.passcolor4f_vertexbuffer = 0;
10101                         rsurface.passcolor4f_bufferoffset = 0;
10102                 }
10103                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10104                 {
10105                         qboolean applycolor = true;
10106                         float one = 1.0;
10107
10108                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10109
10110                         r_refdef.lightmapintensity = 1;
10111                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10112                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10113                 }
10114                 else if (FAKELIGHT_ENABLED)
10115                 {
10116                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10117
10118                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10119                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10120                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10121                 }
10122                 else
10123                 {
10124                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10125
10126                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10127                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10128                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10129                 }
10130
10131                 if(!rsurface.passcolor4f)
10132                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10133
10134                 RSurf_DrawBatch_GL11_ApplyAmbient();
10135                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10136                 if(r_refdef.fogenabled)
10137                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10138                 RSurf_DrawBatch_GL11_ClampColor();
10139
10140                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10141                 R_SetupShader_Generic_NoTexture(false, false);
10142                 RSurf_DrawBatch();
10143         }
10144         else if (!r_refdef.view.showdebug)
10145         {
10146                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10147                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10148                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10149                 {
10150                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10151                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10152                 }
10153                 R_Mesh_PrepareVertices_Generic_Unlock();
10154                 RSurf_DrawBatch();
10155         }
10156         else if (r_showsurfaces.integer == 4)
10157         {
10158                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10159                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10160                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10161                 {
10162                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10163                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10164                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10165                 }
10166                 R_Mesh_PrepareVertices_Generic_Unlock();
10167                 RSurf_DrawBatch();
10168         }
10169         else if (r_showsurfaces.integer == 2)
10170         {
10171                 const int *e;
10172                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10173                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10174                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10175                 {
10176                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10177                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10178                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10179                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10180                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10181                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10182                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10183                 }
10184                 R_Mesh_PrepareVertices_Generic_Unlock();
10185                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10186         }
10187         else
10188         {
10189                 int texturesurfaceindex;
10190                 int k;
10191                 const msurface_t *surface;
10192                 float surfacecolor4f[4];
10193                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10194                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10195                 vi = 0;
10196                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10197                 {
10198                         surface = texturesurfacelist[texturesurfaceindex];
10199                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10200                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10201                         for (j = 0;j < surface->num_vertices;j++)
10202                         {
10203                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10204                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10205                                 vi++;
10206                         }
10207                 }
10208                 R_Mesh_PrepareVertices_Generic_Unlock();
10209                 RSurf_DrawBatch();
10210         }
10211 }
10212
10213 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10214 {
10215         CHECKGLERROR
10216         RSurf_SetupDepthAndCulling();
10217         if (r_showsurfaces.integer)
10218         {
10219                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10220                 return;
10221         }
10222         switch (vid.renderpath)
10223         {
10224         case RENDERPATH_GL20:
10225         case RENDERPATH_D3D9:
10226         case RENDERPATH_D3D10:
10227         case RENDERPATH_D3D11:
10228         case RENDERPATH_SOFT:
10229         case RENDERPATH_GLES2:
10230                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10231                 break;
10232         case RENDERPATH_GL13:
10233         case RENDERPATH_GLES1:
10234                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10235                 break;
10236         case RENDERPATH_GL11:
10237                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10238                 break;
10239         }
10240         CHECKGLERROR
10241 }
10242
10243 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10244 {
10245         CHECKGLERROR
10246         RSurf_SetupDepthAndCulling();
10247         if (r_showsurfaces.integer)
10248         {
10249                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10250                 return;
10251         }
10252         switch (vid.renderpath)
10253         {
10254         case RENDERPATH_GL20:
10255         case RENDERPATH_D3D9:
10256         case RENDERPATH_D3D10:
10257         case RENDERPATH_D3D11:
10258         case RENDERPATH_SOFT:
10259         case RENDERPATH_GLES2:
10260                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10261                 break;
10262         case RENDERPATH_GL13:
10263         case RENDERPATH_GLES1:
10264                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10265                 break;
10266         case RENDERPATH_GL11:
10267                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10268                 break;
10269         }
10270         CHECKGLERROR
10271 }
10272
10273 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10274 {
10275         int i, j;
10276         int texturenumsurfaces, endsurface;
10277         texture_t *texture;
10278         const msurface_t *surface;
10279         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10280
10281         // if the model is static it doesn't matter what value we give for
10282         // wantnormals and wanttangents, so this logic uses only rules applicable
10283         // to a model, knowing that they are meaningless otherwise
10284         if (ent == r_refdef.scene.worldentity)
10285                 RSurf_ActiveWorldEntity();
10286         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10287                 RSurf_ActiveModelEntity(ent, false, false, false);
10288         else
10289         {
10290                 switch (vid.renderpath)
10291                 {
10292                 case RENDERPATH_GL20:
10293                 case RENDERPATH_D3D9:
10294                 case RENDERPATH_D3D10:
10295                 case RENDERPATH_D3D11:
10296                 case RENDERPATH_SOFT:
10297                 case RENDERPATH_GLES2:
10298                         RSurf_ActiveModelEntity(ent, true, true, false);
10299                         break;
10300                 case RENDERPATH_GL11:
10301                 case RENDERPATH_GL13:
10302                 case RENDERPATH_GLES1:
10303                         RSurf_ActiveModelEntity(ent, true, false, false);
10304                         break;
10305                 }
10306         }
10307
10308         if (r_transparentdepthmasking.integer)
10309         {
10310                 qboolean setup = false;
10311                 for (i = 0;i < numsurfaces;i = j)
10312                 {
10313                         j = i + 1;
10314                         surface = rsurface.modelsurfaces + surfacelist[i];
10315                         texture = surface->texture;
10316                         rsurface.texture = R_GetCurrentTexture(texture);
10317                         rsurface.lightmaptexture = NULL;
10318                         rsurface.deluxemaptexture = NULL;
10319                         rsurface.uselightmaptexture = false;
10320                         // scan ahead until we find a different texture
10321                         endsurface = min(i + 1024, numsurfaces);
10322                         texturenumsurfaces = 0;
10323                         texturesurfacelist[texturenumsurfaces++] = surface;
10324                         for (;j < endsurface;j++)
10325                         {
10326                                 surface = rsurface.modelsurfaces + surfacelist[j];
10327                                 if (texture != surface->texture)
10328                                         break;
10329                                 texturesurfacelist[texturenumsurfaces++] = surface;
10330                         }
10331                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10332                                 continue;
10333                         // render the range of surfaces as depth
10334                         if (!setup)
10335                         {
10336                                 setup = true;
10337                                 GL_ColorMask(0,0,0,0);
10338                                 GL_Color(1,1,1,1);
10339                                 GL_DepthTest(true);
10340                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10341                                 GL_DepthMask(true);
10342 //                              R_Mesh_ResetTextureState();
10343                                 R_SetupShader_DepthOrShadow(false);
10344                         }
10345                         RSurf_SetupDepthAndCulling();
10346                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10347                         if (rsurface.batchvertex3fbuffer)
10348                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10349                         else
10350                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10351                         RSurf_DrawBatch();
10352                 }
10353                 if (setup)
10354                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10355         }
10356
10357         for (i = 0;i < numsurfaces;i = j)
10358         {
10359                 j = i + 1;
10360                 surface = rsurface.modelsurfaces + surfacelist[i];
10361                 texture = surface->texture;
10362                 rsurface.texture = R_GetCurrentTexture(texture);
10363                 // scan ahead until we find a different texture
10364                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10365                 texturenumsurfaces = 0;
10366                 texturesurfacelist[texturenumsurfaces++] = surface;
10367                 if(FAKELIGHT_ENABLED)
10368                 {
10369                         rsurface.lightmaptexture = NULL;
10370                         rsurface.deluxemaptexture = NULL;
10371                         rsurface.uselightmaptexture = false;
10372                         for (;j < endsurface;j++)
10373                         {
10374                                 surface = rsurface.modelsurfaces + surfacelist[j];
10375                                 if (texture != surface->texture)
10376                                         break;
10377                                 texturesurfacelist[texturenumsurfaces++] = surface;
10378                         }
10379                 }
10380                 else
10381                 {
10382                         rsurface.lightmaptexture = surface->lightmaptexture;
10383                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10384                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10385                         for (;j < endsurface;j++)
10386                         {
10387                                 surface = rsurface.modelsurfaces + surfacelist[j];
10388                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10389                                         break;
10390                                 texturesurfacelist[texturenumsurfaces++] = surface;
10391                         }
10392                 }
10393                 // render the range of surfaces
10394                 if (ent == r_refdef.scene.worldentity)
10395                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10396                 else
10397                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10398         }
10399         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10400 }
10401
10402 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10403 {
10404         // transparent surfaces get pushed off into the transparent queue
10405         int surfacelistindex;
10406         const msurface_t *surface;
10407         vec3_t tempcenter, center;
10408         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10409         {
10410                 surface = texturesurfacelist[surfacelistindex];
10411                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10412                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10413                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10414                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10415                 if (queueentity->transparent_offset) // transparent offset
10416                 {
10417                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10418                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10419                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10420                 }
10421                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10422         }
10423 }
10424
10425 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10426 {
10427         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10428                 return;
10429         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10430                 return;
10431         RSurf_SetupDepthAndCulling();
10432         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10433         if (rsurface.batchvertex3fbuffer)
10434                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10435         else
10436                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10437         RSurf_DrawBatch();
10438 }
10439
10440 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10441 {
10442         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10443         CHECKGLERROR
10444         if (depthonly)
10445                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10446         else if (prepass)
10447         {
10448                 if (!rsurface.texture->currentnumlayers)
10449                         return;
10450                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10451                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10452                 else
10453                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10454         }
10455         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10456                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10457         else if (!rsurface.texture->currentnumlayers)
10458                 return;
10459         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10460         {
10461                 // in the deferred case, transparent surfaces were queued during prepass
10462                 if (!r_shadow_usingdeferredprepass)
10463                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10464         }
10465         else
10466         {
10467                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10468                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10469         }
10470         CHECKGLERROR
10471 }
10472
10473 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10474 {
10475         int i, j;
10476         texture_t *texture;
10477         R_FrameData_SetMark();
10478         // break the surface list down into batches by texture and use of lightmapping
10479         for (i = 0;i < numsurfaces;i = j)
10480         {
10481                 j = i + 1;
10482                 // texture is the base texture pointer, rsurface.texture is the
10483                 // current frame/skin the texture is directing us to use (for example
10484                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10485                 // use skin 1 instead)
10486                 texture = surfacelist[i]->texture;
10487                 rsurface.texture = R_GetCurrentTexture(texture);
10488                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10489                 {
10490                         // if this texture is not the kind we want, skip ahead to the next one
10491                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10492                                 ;
10493                         continue;
10494                 }
10495                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10496                 {
10497                         rsurface.lightmaptexture = NULL;
10498                         rsurface.deluxemaptexture = NULL;
10499                         rsurface.uselightmaptexture = false;
10500                         // simply scan ahead until we find a different texture or lightmap state
10501                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10502                                 ;
10503                 }
10504                 else
10505                 {
10506                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10507                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10508                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10509                         // simply scan ahead until we find a different texture or lightmap state
10510                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10511                                 ;
10512                 }
10513                 // render the range of surfaces
10514                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10515         }
10516         R_FrameData_ReturnToMark();
10517 }
10518
10519 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10520 {
10521         CHECKGLERROR
10522         if (depthonly)
10523                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10524         else if (prepass)
10525         {
10526                 if (!rsurface.texture->currentnumlayers)
10527                         return;
10528                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10529                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10530                 else
10531                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10532         }
10533         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10534                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10535         else if (!rsurface.texture->currentnumlayers)
10536                 return;
10537         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10538         {
10539                 // in the deferred case, transparent surfaces were queued during prepass
10540                 if (!r_shadow_usingdeferredprepass)
10541                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10542         }
10543         else
10544         {
10545                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10546                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10547         }
10548         CHECKGLERROR
10549 }
10550
10551 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10552 {
10553         int i, j;
10554         texture_t *texture;
10555         R_FrameData_SetMark();
10556         // break the surface list down into batches by texture and use of lightmapping
10557         for (i = 0;i < numsurfaces;i = j)
10558         {
10559                 j = i + 1;
10560                 // texture is the base texture pointer, rsurface.texture is the
10561                 // current frame/skin the texture is directing us to use (for example
10562                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10563                 // use skin 1 instead)
10564                 texture = surfacelist[i]->texture;
10565                 rsurface.texture = R_GetCurrentTexture(texture);
10566                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10567                 {
10568                         // if this texture is not the kind we want, skip ahead to the next one
10569                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10570                                 ;
10571                         continue;
10572                 }
10573                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10574                 {
10575                         rsurface.lightmaptexture = NULL;
10576                         rsurface.deluxemaptexture = NULL;
10577                         rsurface.uselightmaptexture = false;
10578                         // simply scan ahead until we find a different texture or lightmap state
10579                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10580                                 ;
10581                 }
10582                 else
10583                 {
10584                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10585                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10586                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10587                         // simply scan ahead until we find a different texture or lightmap state
10588                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10589                                 ;
10590                 }
10591                 // render the range of surfaces
10592                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10593         }
10594         R_FrameData_ReturnToMark();
10595 }
10596
10597 float locboxvertex3f[6*4*3] =
10598 {
10599         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10600         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10601         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10602         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10603         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10604         1,0,0, 0,0,0, 0,1,0, 1,1,0
10605 };
10606
10607 unsigned short locboxelements[6*2*3] =
10608 {
10609          0, 1, 2, 0, 2, 3,
10610          4, 5, 6, 4, 6, 7,
10611          8, 9,10, 8,10,11,
10612         12,13,14, 12,14,15,
10613         16,17,18, 16,18,19,
10614         20,21,22, 20,22,23
10615 };
10616
10617 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10618 {
10619         int i, j;
10620         cl_locnode_t *loc = (cl_locnode_t *)ent;
10621         vec3_t mins, size;
10622         float vertex3f[6*4*3];
10623         CHECKGLERROR
10624         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10625         GL_DepthMask(false);
10626         GL_DepthRange(0, 1);
10627         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10628         GL_DepthTest(true);
10629         GL_CullFace(GL_NONE);
10630         R_EntityMatrix(&identitymatrix);
10631
10632 //      R_Mesh_ResetTextureState();
10633
10634         i = surfacelist[0];
10635         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10636                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10637                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10638                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10639
10640         if (VectorCompare(loc->mins, loc->maxs))
10641         {
10642                 VectorSet(size, 2, 2, 2);
10643                 VectorMA(loc->mins, -0.5f, size, mins);
10644         }
10645         else
10646         {
10647                 VectorCopy(loc->mins, mins);
10648                 VectorSubtract(loc->maxs, loc->mins, size);
10649         }
10650
10651         for (i = 0;i < 6*4*3;)
10652                 for (j = 0;j < 3;j++, i++)
10653                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10654
10655         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10656         R_SetupShader_Generic_NoTexture(false, false);
10657         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10658 }
10659
10660 void R_DrawLocs(void)
10661 {
10662         int index;
10663         cl_locnode_t *loc, *nearestloc;
10664         vec3_t center;
10665         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10666         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10667         {
10668                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10669                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10670         }
10671 }
10672
10673 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10674 {
10675         if (decalsystem->decals)
10676                 Mem_Free(decalsystem->decals);
10677         memset(decalsystem, 0, sizeof(*decalsystem));
10678 }
10679
10680 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)
10681 {
10682         tridecal_t *decal;
10683         tridecal_t *decals;
10684         int i;
10685
10686         // expand or initialize the system
10687         if (decalsystem->maxdecals <= decalsystem->numdecals)
10688         {
10689                 decalsystem_t old = *decalsystem;
10690                 qboolean useshortelements;
10691                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10692                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10693                 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)));
10694                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10695                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10696                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10697                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10698                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10699                 if (decalsystem->numdecals)
10700                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10701                 if (old.decals)
10702                         Mem_Free(old.decals);
10703                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10704                         decalsystem->element3i[i] = i;
10705                 if (useshortelements)
10706                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10707                                 decalsystem->element3s[i] = i;
10708         }
10709
10710         // grab a decal and search for another free slot for the next one
10711         decals = decalsystem->decals;
10712         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10713         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10714                 ;
10715         decalsystem->freedecal = i;
10716         if (decalsystem->numdecals <= i)
10717                 decalsystem->numdecals = i + 1;
10718
10719         // initialize the decal
10720         decal->lived = 0;
10721         decal->triangleindex = triangleindex;
10722         decal->surfaceindex = surfaceindex;
10723         decal->decalsequence = decalsequence;
10724         decal->color4f[0][0] = c0[0];
10725         decal->color4f[0][1] = c0[1];
10726         decal->color4f[0][2] = c0[2];
10727         decal->color4f[0][3] = 1;
10728         decal->color4f[1][0] = c1[0];
10729         decal->color4f[1][1] = c1[1];
10730         decal->color4f[1][2] = c1[2];
10731         decal->color4f[1][3] = 1;
10732         decal->color4f[2][0] = c2[0];
10733         decal->color4f[2][1] = c2[1];
10734         decal->color4f[2][2] = c2[2];
10735         decal->color4f[2][3] = 1;
10736         decal->vertex3f[0][0] = v0[0];
10737         decal->vertex3f[0][1] = v0[1];
10738         decal->vertex3f[0][2] = v0[2];
10739         decal->vertex3f[1][0] = v1[0];
10740         decal->vertex3f[1][1] = v1[1];
10741         decal->vertex3f[1][2] = v1[2];
10742         decal->vertex3f[2][0] = v2[0];
10743         decal->vertex3f[2][1] = v2[1];
10744         decal->vertex3f[2][2] = v2[2];
10745         decal->texcoord2f[0][0] = t0[0];
10746         decal->texcoord2f[0][1] = t0[1];
10747         decal->texcoord2f[1][0] = t1[0];
10748         decal->texcoord2f[1][1] = t1[1];
10749         decal->texcoord2f[2][0] = t2[0];
10750         decal->texcoord2f[2][1] = t2[1];
10751         TriangleNormal(v0, v1, v2, decal->plane);
10752         VectorNormalize(decal->plane);
10753         decal->plane[3] = DotProduct(v0, decal->plane);
10754 }
10755
10756 extern cvar_t cl_decals_bias;
10757 extern cvar_t cl_decals_models;
10758 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10759 // baseparms, parms, temps
10760 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)
10761 {
10762         int cornerindex;
10763         int index;
10764         float v[9][3];
10765         const float *vertex3f;
10766         const float *normal3f;
10767         int numpoints;
10768         float points[2][9][3];
10769         float temp[3];
10770         float tc[9][2];
10771         float f;
10772         float c[9][4];
10773         const int *e;
10774
10775         e = rsurface.modelelement3i + 3*triangleindex;
10776
10777         vertex3f = rsurface.modelvertex3f;
10778         normal3f = rsurface.modelnormal3f;
10779
10780         if (normal3f)
10781         {
10782                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10783                 {
10784                         index = 3*e[cornerindex];
10785                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10786                 }
10787         }
10788         else
10789         {
10790                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10791                 {
10792                         index = 3*e[cornerindex];
10793                         VectorCopy(vertex3f + index, v[cornerindex]);
10794                 }
10795         }
10796
10797         // cull backfaces
10798         //TriangleNormal(v[0], v[1], v[2], normal);
10799         //if (DotProduct(normal, localnormal) < 0.0f)
10800         //      continue;
10801         // clip by each of the box planes formed from the projection matrix
10802         // if anything survives, we emit the decal
10803         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]);
10804         if (numpoints < 3)
10805                 return;
10806         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]);
10807         if (numpoints < 3)
10808                 return;
10809         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]);
10810         if (numpoints < 3)
10811                 return;
10812         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]);
10813         if (numpoints < 3)
10814                 return;
10815         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]);
10816         if (numpoints < 3)
10817                 return;
10818         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]);
10819         if (numpoints < 3)
10820                 return;
10821         // some part of the triangle survived, so we have to accept it...
10822         if (dynamic)
10823         {
10824                 // dynamic always uses the original triangle
10825                 numpoints = 3;
10826                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10827                 {
10828                         index = 3*e[cornerindex];
10829                         VectorCopy(vertex3f + index, v[cornerindex]);
10830                 }
10831         }
10832         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10833         {
10834                 // convert vertex positions to texcoords
10835                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10836                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10837                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10838                 // calculate distance fade from the projection origin
10839                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10840                 f = bound(0.0f, f, 1.0f);
10841                 c[cornerindex][0] = r * f;
10842                 c[cornerindex][1] = g * f;
10843                 c[cornerindex][2] = b * f;
10844                 c[cornerindex][3] = 1.0f;
10845                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10846         }
10847         if (dynamic)
10848                 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);
10849         else
10850                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10851                         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);
10852 }
10853 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)
10854 {
10855         matrix4x4_t projection;
10856         decalsystem_t *decalsystem;
10857         qboolean dynamic;
10858         dp_model_t *model;
10859         const msurface_t *surface;
10860         const msurface_t *surfaces;
10861         const int *surfacelist;
10862         const texture_t *texture;
10863         int numtriangles;
10864         int numsurfacelist;
10865         int surfacelistindex;
10866         int surfaceindex;
10867         int triangleindex;
10868         float localorigin[3];
10869         float localnormal[3];
10870         float localmins[3];
10871         float localmaxs[3];
10872         float localsize;
10873         //float normal[3];
10874         float planes[6][4];
10875         float angles[3];
10876         bih_t *bih;
10877         int bih_triangles_count;
10878         int bih_triangles[256];
10879         int bih_surfaces[256];
10880
10881         decalsystem = &ent->decalsystem;
10882         model = ent->model;
10883         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10884         {
10885                 R_DecalSystem_Reset(&ent->decalsystem);
10886                 return;
10887         }
10888
10889         if (!model->brush.data_leafs && !cl_decals_models.integer)
10890         {
10891                 if (decalsystem->model)
10892                         R_DecalSystem_Reset(decalsystem);
10893                 return;
10894         }
10895
10896         if (decalsystem->model != model)
10897                 R_DecalSystem_Reset(decalsystem);
10898         decalsystem->model = model;
10899
10900         RSurf_ActiveModelEntity(ent, true, false, false);
10901
10902         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10903         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10904         VectorNormalize(localnormal);
10905         localsize = worldsize*rsurface.inversematrixscale;
10906         localmins[0] = localorigin[0] - localsize;
10907         localmins[1] = localorigin[1] - localsize;
10908         localmins[2] = localorigin[2] - localsize;
10909         localmaxs[0] = localorigin[0] + localsize;
10910         localmaxs[1] = localorigin[1] + localsize;
10911         localmaxs[2] = localorigin[2] + localsize;
10912
10913         //VectorCopy(localnormal, planes[4]);
10914         //VectorVectors(planes[4], planes[2], planes[0]);
10915         AnglesFromVectors(angles, localnormal, NULL, false);
10916         AngleVectors(angles, planes[0], planes[2], planes[4]);
10917         VectorNegate(planes[0], planes[1]);
10918         VectorNegate(planes[2], planes[3]);
10919         VectorNegate(planes[4], planes[5]);
10920         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10921         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10922         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10923         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10924         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10925         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10926
10927 #if 1
10928 // works
10929 {
10930         matrix4x4_t forwardprojection;
10931         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10932         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10933 }
10934 #else
10935 // broken
10936 {
10937         float projectionvector[4][3];
10938         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10939         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10940         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10941         projectionvector[0][0] = planes[0][0] * ilocalsize;
10942         projectionvector[0][1] = planes[1][0] * ilocalsize;
10943         projectionvector[0][2] = planes[2][0] * ilocalsize;
10944         projectionvector[1][0] = planes[0][1] * ilocalsize;
10945         projectionvector[1][1] = planes[1][1] * ilocalsize;
10946         projectionvector[1][2] = planes[2][1] * ilocalsize;
10947         projectionvector[2][0] = planes[0][2] * ilocalsize;
10948         projectionvector[2][1] = planes[1][2] * ilocalsize;
10949         projectionvector[2][2] = planes[2][2] * ilocalsize;
10950         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10951         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10952         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10953         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10954 }
10955 #endif
10956
10957         dynamic = model->surfmesh.isanimated;
10958         numsurfacelist = model->nummodelsurfaces;
10959         surfacelist = model->sortedmodelsurfaces;
10960         surfaces = model->data_surfaces;
10961
10962         bih = NULL;
10963         bih_triangles_count = -1;
10964         if(!dynamic)
10965         {
10966                 if(model->render_bih.numleafs)
10967                         bih = &model->render_bih;
10968                 else if(model->collision_bih.numleafs)
10969                         bih = &model->collision_bih;
10970         }
10971         if(bih)
10972                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10973         if(bih_triangles_count == 0)
10974                 return;
10975         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10976                 return;
10977         if(bih_triangles_count > 0)
10978         {
10979                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10980                 {
10981                         surfaceindex = bih_surfaces[triangleindex];
10982                         surface = surfaces + surfaceindex;
10983                         texture = surface->texture;
10984                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10985                                 continue;
10986                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10987                                 continue;
10988                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10989                 }
10990         }
10991         else
10992         {
10993                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10994                 {
10995                         surfaceindex = surfacelist[surfacelistindex];
10996                         surface = surfaces + surfaceindex;
10997                         // check cull box first because it rejects more than any other check
10998                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10999                                 continue;
11000                         // skip transparent surfaces
11001                         texture = surface->texture;
11002                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11003                                 continue;
11004                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11005                                 continue;
11006                         numtriangles = surface->num_triangles;
11007                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11008                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11009                 }
11010         }
11011 }
11012
11013 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11014 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)
11015 {
11016         int renderentityindex;
11017         float worldmins[3];
11018         float worldmaxs[3];
11019         entity_render_t *ent;
11020
11021         if (!cl_decals_newsystem.integer)
11022                 return;
11023
11024         worldmins[0] = worldorigin[0] - worldsize;
11025         worldmins[1] = worldorigin[1] - worldsize;
11026         worldmins[2] = worldorigin[2] - worldsize;
11027         worldmaxs[0] = worldorigin[0] + worldsize;
11028         worldmaxs[1] = worldorigin[1] + worldsize;
11029         worldmaxs[2] = worldorigin[2] + worldsize;
11030
11031         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11032
11033         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11034         {
11035                 ent = r_refdef.scene.entities[renderentityindex];
11036                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11037                         continue;
11038
11039                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11040         }
11041 }
11042
11043 typedef struct r_decalsystem_splatqueue_s
11044 {
11045         vec3_t worldorigin;
11046         vec3_t worldnormal;
11047         float color[4];
11048         float tcrange[4];
11049         float worldsize;
11050         int decalsequence;
11051 }
11052 r_decalsystem_splatqueue_t;
11053
11054 int r_decalsystem_numqueued = 0;
11055 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11056
11057 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)
11058 {
11059         r_decalsystem_splatqueue_t *queue;
11060
11061         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11062                 return;
11063
11064         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11065         VectorCopy(worldorigin, queue->worldorigin);
11066         VectorCopy(worldnormal, queue->worldnormal);
11067         Vector4Set(queue->color, r, g, b, a);
11068         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11069         queue->worldsize = worldsize;
11070         queue->decalsequence = cl.decalsequence++;
11071 }
11072
11073 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11074 {
11075         int i;
11076         r_decalsystem_splatqueue_t *queue;
11077
11078         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11079                 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);
11080         r_decalsystem_numqueued = 0;
11081 }
11082
11083 extern cvar_t cl_decals_max;
11084 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11085 {
11086         int i;
11087         decalsystem_t *decalsystem = &ent->decalsystem;
11088         int numdecals;
11089         int killsequence;
11090         tridecal_t *decal;
11091         float frametime;
11092         float lifetime;
11093
11094         if (!decalsystem->numdecals)
11095                 return;
11096
11097         if (r_showsurfaces.integer)
11098                 return;
11099
11100         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11101         {
11102                 R_DecalSystem_Reset(decalsystem);
11103                 return;
11104         }
11105
11106         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11107         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11108
11109         if (decalsystem->lastupdatetime)
11110                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11111         else
11112                 frametime = 0;
11113         decalsystem->lastupdatetime = r_refdef.scene.time;
11114         decal = decalsystem->decals;
11115         numdecals = decalsystem->numdecals;
11116
11117         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11118         {
11119                 if (decal->color4f[0][3])
11120                 {
11121                         decal->lived += frametime;
11122                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11123                         {
11124                                 memset(decal, 0, sizeof(*decal));
11125                                 if (decalsystem->freedecal > i)
11126                                         decalsystem->freedecal = i;
11127                         }
11128                 }
11129         }
11130         decal = decalsystem->decals;
11131         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11132                 numdecals--;
11133
11134         // collapse the array by shuffling the tail decals into the gaps
11135         for (;;)
11136         {
11137                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11138                         decalsystem->freedecal++;
11139                 if (decalsystem->freedecal == numdecals)
11140                         break;
11141                 decal[decalsystem->freedecal] = decal[--numdecals];
11142         }
11143
11144         decalsystem->numdecals = numdecals;
11145
11146         if (numdecals <= 0)
11147         {
11148                 // if there are no decals left, reset decalsystem
11149                 R_DecalSystem_Reset(decalsystem);
11150         }
11151 }
11152
11153 extern skinframe_t *decalskinframe;
11154 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11155 {
11156         int i;
11157         decalsystem_t *decalsystem = &ent->decalsystem;
11158         int numdecals;
11159         tridecal_t *decal;
11160         float faderate;
11161         float alpha;
11162         float *v3f;
11163         float *c4f;
11164         float *t2f;
11165         const int *e;
11166         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11167         int numtris = 0;
11168
11169         numdecals = decalsystem->numdecals;
11170         if (!numdecals)
11171                 return;
11172
11173         if (r_showsurfaces.integer)
11174                 return;
11175
11176         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11177         {
11178                 R_DecalSystem_Reset(decalsystem);
11179                 return;
11180         }
11181
11182         // if the model is static it doesn't matter what value we give for
11183         // wantnormals and wanttangents, so this logic uses only rules applicable
11184         // to a model, knowing that they are meaningless otherwise
11185         if (ent == r_refdef.scene.worldentity)
11186                 RSurf_ActiveWorldEntity();
11187         else
11188                 RSurf_ActiveModelEntity(ent, false, false, false);
11189
11190         decalsystem->lastupdatetime = r_refdef.scene.time;
11191         decal = decalsystem->decals;
11192
11193         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11194
11195         // update vertex positions for animated models
11196         v3f = decalsystem->vertex3f;
11197         c4f = decalsystem->color4f;
11198         t2f = decalsystem->texcoord2f;
11199         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11200         {
11201                 if (!decal->color4f[0][3])
11202                         continue;
11203
11204                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11205                         continue;
11206
11207                 // skip backfaces
11208                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11209                         continue;
11210
11211                 // update color values for fading decals
11212                 if (decal->lived >= cl_decals_time.value)
11213                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11214                 else
11215                         alpha = 1.0f;
11216
11217                 c4f[ 0] = decal->color4f[0][0] * alpha;
11218                 c4f[ 1] = decal->color4f[0][1] * alpha;
11219                 c4f[ 2] = decal->color4f[0][2] * alpha;
11220                 c4f[ 3] = 1;
11221                 c4f[ 4] = decal->color4f[1][0] * alpha;
11222                 c4f[ 5] = decal->color4f[1][1] * alpha;
11223                 c4f[ 6] = decal->color4f[1][2] * alpha;
11224                 c4f[ 7] = 1;
11225                 c4f[ 8] = decal->color4f[2][0] * alpha;
11226                 c4f[ 9] = decal->color4f[2][1] * alpha;
11227                 c4f[10] = decal->color4f[2][2] * alpha;
11228                 c4f[11] = 1;
11229
11230                 t2f[0] = decal->texcoord2f[0][0];
11231                 t2f[1] = decal->texcoord2f[0][1];
11232                 t2f[2] = decal->texcoord2f[1][0];
11233                 t2f[3] = decal->texcoord2f[1][1];
11234                 t2f[4] = decal->texcoord2f[2][0];
11235                 t2f[5] = decal->texcoord2f[2][1];
11236
11237                 // update vertex positions for animated models
11238                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11239                 {
11240                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11241                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11242                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11243                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11244                 }
11245                 else
11246                 {
11247                         VectorCopy(decal->vertex3f[0], v3f);
11248                         VectorCopy(decal->vertex3f[1], v3f + 3);
11249                         VectorCopy(decal->vertex3f[2], v3f + 6);
11250                 }
11251
11252                 if (r_refdef.fogenabled)
11253                 {
11254                         alpha = RSurf_FogVertex(v3f);
11255                         VectorScale(c4f, alpha, c4f);
11256                         alpha = RSurf_FogVertex(v3f + 3);
11257                         VectorScale(c4f + 4, alpha, c4f + 4);
11258                         alpha = RSurf_FogVertex(v3f + 6);
11259                         VectorScale(c4f + 8, alpha, c4f + 8);
11260                 }
11261
11262                 v3f += 9;
11263                 c4f += 12;
11264                 t2f += 6;
11265                 numtris++;
11266         }
11267
11268         if (numtris > 0)
11269         {
11270                 r_refdef.stats.drawndecals += numtris;
11271
11272                 // now render the decals all at once
11273                 // (this assumes they all use one particle font texture!)
11274                 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);
11275 //              R_Mesh_ResetTextureState();
11276                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11277                 GL_DepthMask(false);
11278                 GL_DepthRange(0, 1);
11279                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11280                 GL_DepthTest(true);
11281                 GL_CullFace(GL_NONE);
11282                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11283                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11284                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11285         }
11286 }
11287
11288 static void R_DrawModelDecals(void)
11289 {
11290         int i, numdecals;
11291
11292         // fade faster when there are too many decals
11293         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11294         for (i = 0;i < r_refdef.scene.numentities;i++)
11295                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11296
11297         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11298         for (i = 0;i < r_refdef.scene.numentities;i++)
11299                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11300                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11301
11302         R_DecalSystem_ApplySplatEntitiesQueue();
11303
11304         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11305         for (i = 0;i < r_refdef.scene.numentities;i++)
11306                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11307
11308         r_refdef.stats.totaldecals += numdecals;
11309
11310         if (r_showsurfaces.integer)
11311                 return;
11312
11313         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11314
11315         for (i = 0;i < r_refdef.scene.numentities;i++)
11316         {
11317                 if (!r_refdef.viewcache.entityvisible[i])
11318                         continue;
11319                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11320                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11321         }
11322 }
11323
11324 extern cvar_t mod_collision_bih;
11325 static void R_DrawDebugModel(void)
11326 {
11327         entity_render_t *ent = rsurface.entity;
11328         int i, j, k, l, flagsmask;
11329         const msurface_t *surface;
11330         dp_model_t *model = ent->model;
11331         vec3_t v;
11332
11333         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11334                 return;
11335
11336         if (r_showoverdraw.value > 0)
11337         {
11338                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11339                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11340                 R_SetupShader_Generic_NoTexture(false, false);
11341                 GL_DepthTest(false);
11342                 GL_DepthMask(false);
11343                 GL_DepthRange(0, 1);
11344                 GL_BlendFunc(GL_ONE, GL_ONE);
11345                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11346                 {
11347                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11348                                 continue;
11349                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11350                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11351                         {
11352                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11353                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11354                                 if (!rsurface.texture->currentlayers->depthmask)
11355                                         GL_Color(c, 0, 0, 1.0f);
11356                                 else if (ent == r_refdef.scene.worldentity)
11357                                         GL_Color(c, c, c, 1.0f);
11358                                 else
11359                                         GL_Color(0, c, 0, 1.0f);
11360                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11361                                 RSurf_DrawBatch();
11362                         }
11363                 }
11364                 rsurface.texture = NULL;
11365         }
11366
11367         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11368
11369 //      R_Mesh_ResetTextureState();
11370         R_SetupShader_Generic_NoTexture(false, false);
11371         GL_DepthRange(0, 1);
11372         GL_DepthTest(!r_showdisabledepthtest.integer);
11373         GL_DepthMask(false);
11374         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11375
11376         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11377         {
11378                 int triangleindex;
11379                 int bihleafindex;
11380                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11381                 const q3mbrush_t *brush;
11382                 const bih_t *bih = &model->collision_bih;
11383                 const bih_leaf_t *bihleaf;
11384                 float vertex3f[3][3];
11385                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11386                 cullbox = false;
11387                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11388                 {
11389                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11390                                 continue;
11391                         switch (bihleaf->type)
11392                         {
11393                         case BIH_BRUSH:
11394                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11395                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11396                                 {
11397                                         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);
11398                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11399                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11400                                 }
11401                                 break;
11402                         case BIH_COLLISIONTRIANGLE:
11403                                 triangleindex = bihleaf->itemindex;
11404                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11405                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11406                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11407                                 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);
11408                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11409                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11410                                 break;
11411                         case BIH_RENDERTRIANGLE:
11412                                 triangleindex = bihleaf->itemindex;
11413                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11414                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11415                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11416                                 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);
11417                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11418                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11419                                 break;
11420                         }
11421                 }
11422         }
11423
11424         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11425
11426 #ifndef USE_GLES2
11427         if (r_showtris.integer && qglPolygonMode)
11428         {
11429                 if (r_showdisabledepthtest.integer)
11430                 {
11431                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11432                         GL_DepthMask(false);
11433                 }
11434                 else
11435                 {
11436                         GL_BlendFunc(GL_ONE, GL_ZERO);
11437                         GL_DepthMask(true);
11438                 }
11439                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11440                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11441                 {
11442                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11443                                 continue;
11444                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11445                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11446                         {
11447                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11448                                 if (!rsurface.texture->currentlayers->depthmask)
11449                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11450                                 else if (ent == r_refdef.scene.worldentity)
11451                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11452                                 else
11453                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11454                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11455                                 RSurf_DrawBatch();
11456                         }
11457                 }
11458                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11459                 rsurface.texture = NULL;
11460         }
11461
11462         if (r_shownormals.value != 0 && qglBegin)
11463         {
11464                 if (r_showdisabledepthtest.integer)
11465                 {
11466                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11467                         GL_DepthMask(false);
11468                 }
11469                 else
11470                 {
11471                         GL_BlendFunc(GL_ONE, GL_ZERO);
11472                         GL_DepthMask(true);
11473                 }
11474                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11475                 {
11476                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11477                                 continue;
11478                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11479                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11480                         {
11481                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11482                                 qglBegin(GL_LINES);
11483                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11484                                 {
11485                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11486                                         {
11487                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11488                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11489                                                 qglVertex3f(v[0], v[1], v[2]);
11490                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11491                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11492                                                 qglVertex3f(v[0], v[1], v[2]);
11493                                         }
11494                                 }
11495                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11496                                 {
11497                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11498                                         {
11499                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11500                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11501                                                 qglVertex3f(v[0], v[1], v[2]);
11502                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11503                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11504                                                 qglVertex3f(v[0], v[1], v[2]);
11505                                         }
11506                                 }
11507                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11508                                 {
11509                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11510                                         {
11511                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11512                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11513                                                 qglVertex3f(v[0], v[1], v[2]);
11514                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11515                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11516                                                 qglVertex3f(v[0], v[1], v[2]);
11517                                         }
11518                                 }
11519                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11520                                 {
11521                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11522                                         {
11523                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11524                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11525                                                 qglVertex3f(v[0], v[1], v[2]);
11526                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11527                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11528                                                 qglVertex3f(v[0], v[1], v[2]);
11529                                         }
11530                                 }
11531                                 qglEnd();
11532                                 CHECKGLERROR
11533                         }
11534                 }
11535                 rsurface.texture = NULL;
11536         }
11537 #endif
11538 }
11539
11540 int r_maxsurfacelist = 0;
11541 const msurface_t **r_surfacelist = NULL;
11542 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11543 {
11544         int i, j, endj, flagsmask;
11545         dp_model_t *model = r_refdef.scene.worldmodel;
11546         msurface_t *surfaces;
11547         unsigned char *update;
11548         int numsurfacelist = 0;
11549         if (model == NULL)
11550                 return;
11551
11552         if (r_maxsurfacelist < model->num_surfaces)
11553         {
11554                 r_maxsurfacelist = model->num_surfaces;
11555                 if (r_surfacelist)
11556                         Mem_Free((msurface_t**)r_surfacelist);
11557                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11558         }
11559
11560         RSurf_ActiveWorldEntity();
11561
11562         surfaces = model->data_surfaces;
11563         update = model->brushq1.lightmapupdateflags;
11564
11565         // update light styles on this submodel
11566         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11567         {
11568                 model_brush_lightstyleinfo_t *style;
11569                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11570                 {
11571                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11572                         {
11573                                 int *list = style->surfacelist;
11574                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11575                                 for (j = 0;j < style->numsurfaces;j++)
11576                                         update[list[j]] = true;
11577                         }
11578                 }
11579         }
11580
11581         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11582
11583         if (debug)
11584         {
11585                 R_DrawDebugModel();
11586                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11587                 return;
11588         }
11589
11590         rsurface.lightmaptexture = NULL;
11591         rsurface.deluxemaptexture = NULL;
11592         rsurface.uselightmaptexture = false;
11593         rsurface.texture = NULL;
11594         rsurface.rtlight = NULL;
11595         numsurfacelist = 0;
11596         // add visible surfaces to draw list
11597         for (i = 0;i < model->nummodelsurfaces;i++)
11598         {
11599                 j = model->sortedmodelsurfaces[i];
11600                 if (r_refdef.viewcache.world_surfacevisible[j])
11601                         r_surfacelist[numsurfacelist++] = surfaces + j;
11602         }
11603         // update lightmaps if needed
11604         if (model->brushq1.firstrender)
11605         {
11606                 model->brushq1.firstrender = false;
11607                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11608                         if (update[j])
11609                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11610         }
11611         else if (update)
11612         {
11613                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11614                         if (r_refdef.viewcache.world_surfacevisible[j])
11615                                 if (update[j])
11616                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11617         }
11618         // don't do anything if there were no surfaces
11619         if (!numsurfacelist)
11620         {
11621                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11622                 return;
11623         }
11624         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11625
11626         // add to stats if desired
11627         if (r_speeds.integer && !skysurfaces && !depthonly)
11628         {
11629                 r_refdef.stats.world_surfaces += numsurfacelist;
11630                 for (j = 0;j < numsurfacelist;j++)
11631                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11632         }
11633
11634         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11635 }
11636
11637 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11638 {
11639         int i, j, endj, flagsmask;
11640         dp_model_t *model = ent->model;
11641         msurface_t *surfaces;
11642         unsigned char *update;
11643         int numsurfacelist = 0;
11644         if (model == NULL)
11645                 return;
11646
11647         if (r_maxsurfacelist < model->num_surfaces)
11648         {
11649                 r_maxsurfacelist = model->num_surfaces;
11650                 if (r_surfacelist)
11651                         Mem_Free((msurface_t **)r_surfacelist);
11652                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11653         }
11654
11655         // if the model is static it doesn't matter what value we give for
11656         // wantnormals and wanttangents, so this logic uses only rules applicable
11657         // to a model, knowing that they are meaningless otherwise
11658         if (ent == r_refdef.scene.worldentity)
11659                 RSurf_ActiveWorldEntity();
11660         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11661                 RSurf_ActiveModelEntity(ent, false, false, false);
11662         else if (prepass)
11663                 RSurf_ActiveModelEntity(ent, true, true, true);
11664         else if (depthonly)
11665         {
11666                 switch (vid.renderpath)
11667                 {
11668                 case RENDERPATH_GL20:
11669                 case RENDERPATH_D3D9:
11670                 case RENDERPATH_D3D10:
11671                 case RENDERPATH_D3D11:
11672                 case RENDERPATH_SOFT:
11673                 case RENDERPATH_GLES2:
11674                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11675                         break;
11676                 case RENDERPATH_GL11:
11677                 case RENDERPATH_GL13:
11678                 case RENDERPATH_GLES1:
11679                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11680                         break;
11681                 }
11682         }
11683         else
11684         {
11685                 switch (vid.renderpath)
11686                 {
11687                 case RENDERPATH_GL20:
11688                 case RENDERPATH_D3D9:
11689                 case RENDERPATH_D3D10:
11690                 case RENDERPATH_D3D11:
11691                 case RENDERPATH_SOFT:
11692                 case RENDERPATH_GLES2:
11693                         RSurf_ActiveModelEntity(ent, true, true, false);
11694                         break;
11695                 case RENDERPATH_GL11:
11696                 case RENDERPATH_GL13:
11697                 case RENDERPATH_GLES1:
11698                         RSurf_ActiveModelEntity(ent, true, false, false);
11699                         break;
11700                 }
11701         }
11702
11703         surfaces = model->data_surfaces;
11704         update = model->brushq1.lightmapupdateflags;
11705
11706         // update light styles
11707         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11708         {
11709                 model_brush_lightstyleinfo_t *style;
11710                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11711                 {
11712                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11713                         {
11714                                 int *list = style->surfacelist;
11715                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11716                                 for (j = 0;j < style->numsurfaces;j++)
11717                                         update[list[j]] = true;
11718                         }
11719                 }
11720         }
11721
11722         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11723
11724         if (debug)
11725         {
11726                 R_DrawDebugModel();
11727                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11728                 return;
11729         }
11730
11731         rsurface.lightmaptexture = NULL;
11732         rsurface.deluxemaptexture = NULL;
11733         rsurface.uselightmaptexture = false;
11734         rsurface.texture = NULL;
11735         rsurface.rtlight = NULL;
11736         numsurfacelist = 0;
11737         // add visible surfaces to draw list
11738         for (i = 0;i < model->nummodelsurfaces;i++)
11739                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11740         // don't do anything if there were no surfaces
11741         if (!numsurfacelist)
11742         {
11743                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11744                 return;
11745         }
11746         // update lightmaps if needed
11747         if (update)
11748         {
11749                 int updated = 0;
11750                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11751                 {
11752                         if (update[j])
11753                         {
11754                                 updated++;
11755                                 R_BuildLightMap(ent, surfaces + j);
11756                         }
11757                 }
11758         }
11759         if (update)
11760                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11761                         if (update[j])
11762                                 R_BuildLightMap(ent, surfaces + j);
11763         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11764
11765         // add to stats if desired
11766         if (r_speeds.integer && !skysurfaces && !depthonly)
11767         {
11768                 r_refdef.stats.entities_surfaces += numsurfacelist;
11769                 for (j = 0;j < numsurfacelist;j++)
11770                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11771         }
11772
11773         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11774 }
11775
11776 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11777 {
11778         static texture_t texture;
11779         static msurface_t surface;
11780         const msurface_t *surfacelist = &surface;
11781
11782         // fake enough texture and surface state to render this geometry
11783
11784         texture.update_lastrenderframe = -1; // regenerate this texture
11785         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11786         texture.currentskinframe = skinframe;
11787         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11788         texture.offsetmapping = OFFSETMAPPING_OFF;
11789         texture.offsetscale = 1;
11790         texture.specularscalemod = 1;
11791         texture.specularpowermod = 1;
11792
11793         surface.texture = &texture;
11794         surface.num_triangles = numtriangles;
11795         surface.num_firsttriangle = firsttriangle;
11796         surface.num_vertices = numvertices;
11797         surface.num_firstvertex = firstvertex;
11798
11799         // now render it
11800         rsurface.texture = R_GetCurrentTexture(surface.texture);
11801         rsurface.lightmaptexture = NULL;
11802         rsurface.deluxemaptexture = NULL;
11803         rsurface.uselightmaptexture = false;
11804         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11805 }
11806
11807 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)
11808 {
11809         static msurface_t surface;
11810         const msurface_t *surfacelist = &surface;
11811
11812         // fake enough texture and surface state to render this geometry
11813         surface.texture = texture;
11814         surface.num_triangles = numtriangles;
11815         surface.num_firsttriangle = firsttriangle;
11816         surface.num_vertices = numvertices;
11817         surface.num_firstvertex = firstvertex;
11818
11819         // now render it
11820         rsurface.texture = R_GetCurrentTexture(surface.texture);
11821         rsurface.lightmaptexture = NULL;
11822         rsurface.deluxemaptexture = NULL;
11823         rsurface.uselightmaptexture = false;
11824         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11825 }