]> git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/darkplaces-src/gl_rmain.c
184aa423735a66bf58ad14bf7cd5d503f2b7f41c
[voretournament/voretournament.git] / misc / source / darkplaces-src / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
88 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
91 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
92 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
101 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
125 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
135
136 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
137 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
138 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
139 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
140 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
141 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
142 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
143 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
144
145 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
146 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
147
148 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
149 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
150 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
151
152 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
153 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
154 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
155 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
156 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
157 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
158 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
159 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
160 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
161
162 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
163 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
164 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
165 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
166 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
167 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
168 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
169 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
170 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
171 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
172 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
173 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
174 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
175 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
176 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
177 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
180
181 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
182 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
183 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
184 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
185 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
186 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
187 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
188 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
189 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
190
191 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
192 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
193 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
194 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
195
196 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
197 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
198
199 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
200 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
201 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
202 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
203 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
204
205 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
206 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
207 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
208 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
209 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
210 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
211 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
212 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
213 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
214 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
215
216 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
217
218 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
219
220 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
221
222 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
223
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
226
227 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
228
229 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
230
231 extern cvar_t v_glslgamma;
232 extern cvar_t v_glslgamma_2d;
233
234 extern qboolean v_flipped_state;
235
236 r_framebufferstate_t r_fb;
237
238 /// shadow volume bsp struct with automatically growing nodes buffer
239 svbsp_t r_svbsp;
240
241 rtexture_t *r_texture_blanknormalmap;
242 rtexture_t *r_texture_white;
243 rtexture_t *r_texture_grey128;
244 rtexture_t *r_texture_black;
245 rtexture_t *r_texture_notexture;
246 rtexture_t *r_texture_whitecube;
247 rtexture_t *r_texture_normalizationcube;
248 rtexture_t *r_texture_fogattenuation;
249 rtexture_t *r_texture_fogheighttexture;
250 rtexture_t *r_texture_gammaramps;
251 unsigned int r_texture_gammaramps_serial;
252 //rtexture_t *r_texture_fogintensity;
253 rtexture_t *r_texture_reflectcube;
254
255 // TODO: hash lookups?
256 typedef struct cubemapinfo_s
257 {
258         char basename[64];
259         rtexture_t *texture;
260 }
261 cubemapinfo_t;
262
263 int r_texture_numcubemaps;
264 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
265
266 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
267 unsigned int r_numqueries;
268 unsigned int r_maxqueries;
269
270 typedef struct r_qwskincache_s
271 {
272         char name[MAX_QPATH];
273         skinframe_t *skinframe;
274 }
275 r_qwskincache_t;
276
277 static r_qwskincache_t *r_qwskincache;
278 static int r_qwskincache_size;
279
280 /// vertex coordinates for a quad that covers the screen exactly
281 extern const float r_screenvertex3f[12];
282 extern const float r_d3dscreenvertex3f[12];
283 const float r_screenvertex3f[12] =
284 {
285         0, 0, 0,
286         1, 0, 0,
287         1, 1, 0,
288         0, 1, 0
289 };
290 const float r_d3dscreenvertex3f[12] =
291 {
292         0, 1, 0,
293         1, 1, 0,
294         1, 0, 0,
295         0, 0, 0
296 };
297
298 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
299 {
300         int i;
301         for (i = 0;i < verts;i++)
302         {
303                 out[0] = in[0] * r;
304                 out[1] = in[1] * g;
305                 out[2] = in[2] * b;
306                 out[3] = in[3];
307                 in += 4;
308                 out += 4;
309         }
310 }
311
312 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = r;
318                 out[1] = g;
319                 out[2] = b;
320                 out[3] = a;
321                 out += 4;
322         }
323 }
324
325 // FIXME: move this to client?
326 void FOG_clear(void)
327 {
328         if (gamemode == GAME_NEHAHRA)
329         {
330                 Cvar_Set("gl_fogenable", "0");
331                 Cvar_Set("gl_fogdensity", "0.2");
332                 Cvar_Set("gl_fogred", "0.3");
333                 Cvar_Set("gl_foggreen", "0.3");
334                 Cvar_Set("gl_fogblue", "0.3");
335         }
336         r_refdef.fog_density = 0;
337         r_refdef.fog_red = 0;
338         r_refdef.fog_green = 0;
339         r_refdef.fog_blue = 0;
340         r_refdef.fog_alpha = 1;
341         r_refdef.fog_start = 0;
342         r_refdef.fog_end = 16384;
343         r_refdef.fog_height = 1<<30;
344         r_refdef.fog_fadedepth = 128;
345         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
346 }
347
348 static void R_BuildBlankTextures(void)
349 {
350         unsigned char data[4];
351         data[2] = 128; // normal X
352         data[1] = 128; // normal Y
353         data[0] = 255; // normal Z
354         data[3] = 255; // height
355         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 255;
357         data[1] = 255;
358         data[2] = 255;
359         data[3] = 255;
360         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361         data[0] = 128;
362         data[1] = 128;
363         data[2] = 128;
364         data[3] = 255;
365         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366         data[0] = 0;
367         data[1] = 0;
368         data[2] = 0;
369         data[3] = 255;
370         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371 }
372
373 static void R_BuildNoTexture(void)
374 {
375         int x, y;
376         unsigned char pix[16][16][4];
377         // this makes a light grey/dark grey checkerboard texture
378         for (y = 0;y < 16;y++)
379         {
380                 for (x = 0;x < 16;x++)
381                 {
382                         if ((y < 8) ^ (x < 8))
383                         {
384                                 pix[y][x][0] = 128;
385                                 pix[y][x][1] = 128;
386                                 pix[y][x][2] = 128;
387                                 pix[y][x][3] = 255;
388                         }
389                         else
390                         {
391                                 pix[y][x][0] = 64;
392                                 pix[y][x][1] = 64;
393                                 pix[y][x][2] = 64;
394                                 pix[y][x][3] = 255;
395                         }
396                 }
397         }
398         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildWhiteCube(void)
402 {
403         unsigned char data[6*1*1*4];
404         memset(data, 255, sizeof(data));
405         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
406 }
407
408 static void R_BuildNormalizationCube(void)
409 {
410         int x, y, side;
411         vec3_t v;
412         vec_t s, t, intensity;
413 #define NORMSIZE 64
414         unsigned char *data;
415         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
416         for (side = 0;side < 6;side++)
417         {
418                 for (y = 0;y < NORMSIZE;y++)
419                 {
420                         for (x = 0;x < NORMSIZE;x++)
421                         {
422                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424                                 switch(side)
425                                 {
426                                 default:
427                                 case 0:
428                                         v[0] = 1;
429                                         v[1] = -t;
430                                         v[2] = -s;
431                                         break;
432                                 case 1:
433                                         v[0] = -1;
434                                         v[1] = -t;
435                                         v[2] = s;
436                                         break;
437                                 case 2:
438                                         v[0] = s;
439                                         v[1] = 1;
440                                         v[2] = t;
441                                         break;
442                                 case 3:
443                                         v[0] = s;
444                                         v[1] = -1;
445                                         v[2] = -t;
446                                         break;
447                                 case 4:
448                                         v[0] = s;
449                                         v[1] = -t;
450                                         v[2] = 1;
451                                         break;
452                                 case 5:
453                                         v[0] = -s;
454                                         v[1] = -t;
455                                         v[2] = -1;
456                                         break;
457                                 }
458                                 intensity = 127.0f / sqrt(DotProduct(v, v));
459                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
460                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
461                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
462                                 data[((side*64+y)*64+x)*4+3] = 255;
463                         }
464                 }
465         }
466         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
467         Mem_Free(data);
468 }
469
470 static void R_BuildFogTexture(void)
471 {
472         int x, b;
473 #define FOGWIDTH 256
474         unsigned char data1[FOGWIDTH][4];
475         //unsigned char data2[FOGWIDTH][4];
476         double d, r, alpha;
477
478         r_refdef.fogmasktable_start = r_refdef.fog_start;
479         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
480         r_refdef.fogmasktable_range = r_refdef.fogrange;
481         r_refdef.fogmasktable_density = r_refdef.fog_density;
482
483         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
484         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485         {
486                 d = (x * r - r_refdef.fogmasktable_start);
487                 if(developer_extra.integer)
488                         Con_DPrintf("%f ", d);
489                 d = max(0, d);
490                 if (r_fog_exp2.integer)
491                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492                 else
493                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
494                 if(developer_extra.integer)
495                         Con_DPrintf(" : %f ", alpha);
496                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
497                 if(developer_extra.integer)
498                         Con_DPrintf(" = %f\n", alpha);
499                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
500         }
501
502         for (x = 0;x < FOGWIDTH;x++)
503         {
504                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
505                 data1[x][0] = b;
506                 data1[x][1] = b;
507                 data1[x][2] = b;
508                 data1[x][3] = 255;
509                 //data2[x][0] = 255 - b;
510                 //data2[x][1] = 255 - b;
511                 //data2[x][2] = 255 - b;
512                 //data2[x][3] = 255;
513         }
514         if (r_texture_fogattenuation)
515         {
516                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518         }
519         else
520         {
521                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
522                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
523         }
524 }
525
526 static void R_BuildFogHeightTexture(void)
527 {
528         unsigned char *inpixels;
529         int size;
530         int x;
531         int y;
532         int j;
533         float c[4];
534         float f;
535         inpixels = NULL;
536         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
537         if (r_refdef.fogheighttexturename[0])
538                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
539         if (!inpixels)
540         {
541                 r_refdef.fog_height_tablesize = 0;
542                 if (r_texture_fogheighttexture)
543                         R_FreeTexture(r_texture_fogheighttexture);
544                 r_texture_fogheighttexture = NULL;
545                 if (r_refdef.fog_height_table2d)
546                         Mem_Free(r_refdef.fog_height_table2d);
547                 r_refdef.fog_height_table2d = NULL;
548                 if (r_refdef.fog_height_table1d)
549                         Mem_Free(r_refdef.fog_height_table1d);
550                 r_refdef.fog_height_table1d = NULL;
551                 return;
552         }
553         size = image_width;
554         r_refdef.fog_height_tablesize = size;
555         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
556         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
557         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558         Mem_Free(inpixels);
559         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
560         // average fog color table accounting for every fog layer between a point
561         // and the camera.  (Note: attenuation is handled separately!)
562         for (y = 0;y < size;y++)
563         {
564                 for (x = 0;x < size;x++)
565                 {
566                         Vector4Clear(c);
567                         f = 0;
568                         if (x < y)
569                         {
570                                 for (j = x;j <= y;j++)
571                                 {
572                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
573                                         f++;
574                                 }
575                         }
576                         else
577                         {
578                                 for (j = x;j >= y;j--)
579                                 {
580                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
581                                         f++;
582                                 }
583                         }
584                         f = 1.0f / f;
585                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
589                 }
590         }
591         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
592 }
593
594 //=======================================================================================================================================================
595
596 static const char *builtinshaderstring =
597 #include "shader_glsl.h"
598 ;
599
600 const char *builtinhlslshaderstring =
601 #include "shader_hlsl.h"
602 ;
603
604 char *glslshaderstring = NULL;
605 char *hlslshaderstring = NULL;
606
607 //=======================================================================================================================================================
608
609 typedef struct shaderpermutationinfo_s
610 {
611         const char *pretext;
612         const char *name;
613 }
614 shaderpermutationinfo_t;
615
616 typedef struct shadermodeinfo_s
617 {
618         const char *vertexfilename;
619         const char *geometryfilename;
620         const char *fragmentfilename;
621         const char *pretext;
622         const char *name;
623 }
624 shadermodeinfo_t;
625
626 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
627 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
628 {
629         {"#define USEDIFFUSE\n", " diffuse"},
630         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
631         {"#define USEVIEWTINT\n", " viewtint"},
632         {"#define USECOLORMAPPING\n", " colormapping"},
633         {"#define USESATURATION\n", " saturation"},
634         {"#define USEFOGINSIDE\n", " foginside"},
635         {"#define USEFOGOUTSIDE\n", " fogoutside"},
636         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
637         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
638         {"#define USEGAMMARAMPS\n", " gammaramps"},
639         {"#define USECUBEFILTER\n", " cubefilter"},
640         {"#define USEGLOW\n", " glow"},
641         {"#define USEBLOOM\n", " bloom"},
642         {"#define USESPECULAR\n", " specular"},
643         {"#define USEPOSTPROCESSING\n", " postprocessing"},
644         {"#define USEREFLECTION\n", " reflection"},
645         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
646         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
647         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
656         {"#define USETRIPPY\n", " trippy"},
657         {"#define USEDEPTHRGB\n", " depthrgb"},
658         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
659 };
660
661 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
662 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
663 {
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
682 };
683
684 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 struct r_glsl_permutation_s;
707 typedef struct r_glsl_permutation_s
708 {
709         /// hash lookup data
710         struct r_glsl_permutation_s *hashnext;
711         unsigned int mode;
712         unsigned int permutation;
713
714         /// indicates if we have tried compiling this permutation already
715         qboolean compiled;
716         /// 0 if compilation failed
717         int program;
718         // texture units assigned to each detected uniform
719         int tex_Texture_First;
720         int tex_Texture_Second;
721         int tex_Texture_GammaRamps;
722         int tex_Texture_Normal;
723         int tex_Texture_Color;
724         int tex_Texture_Gloss;
725         int tex_Texture_Glow;
726         int tex_Texture_SecondaryNormal;
727         int tex_Texture_SecondaryColor;
728         int tex_Texture_SecondaryGloss;
729         int tex_Texture_SecondaryGlow;
730         int tex_Texture_Pants;
731         int tex_Texture_Shirt;
732         int tex_Texture_FogHeightTexture;
733         int tex_Texture_FogMask;
734         int tex_Texture_Lightmap;
735         int tex_Texture_Deluxemap;
736         int tex_Texture_Attenuation;
737         int tex_Texture_Cube;
738         int tex_Texture_Refraction;
739         int tex_Texture_Reflection;
740         int tex_Texture_ShadowMap2D;
741         int tex_Texture_CubeProjection;
742         int tex_Texture_ScreenNormalMap;
743         int tex_Texture_ScreenDiffuse;
744         int tex_Texture_ScreenSpecular;
745         int tex_Texture_ReflectMask;
746         int tex_Texture_ReflectCube;
747         int tex_Texture_BounceGrid;
748         /// locations of detected uniforms in program object, or -1 if not found
749         int loc_Texture_First;
750         int loc_Texture_Second;
751         int loc_Texture_GammaRamps;
752         int loc_Texture_Normal;
753         int loc_Texture_Color;
754         int loc_Texture_Gloss;
755         int loc_Texture_Glow;
756         int loc_Texture_SecondaryNormal;
757         int loc_Texture_SecondaryColor;
758         int loc_Texture_SecondaryGloss;
759         int loc_Texture_SecondaryGlow;
760         int loc_Texture_Pants;
761         int loc_Texture_Shirt;
762         int loc_Texture_FogHeightTexture;
763         int loc_Texture_FogMask;
764         int loc_Texture_Lightmap;
765         int loc_Texture_Deluxemap;
766         int loc_Texture_Attenuation;
767         int loc_Texture_Cube;
768         int loc_Texture_Refraction;
769         int loc_Texture_Reflection;
770         int loc_Texture_ShadowMap2D;
771         int loc_Texture_CubeProjection;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
854         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
855         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
856 };
857 #define SHADERSTATICPARMS_COUNT 11
858
859 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
860 static int shaderstaticparms_count = 0;
861
862 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
863 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
864
865 extern qboolean r_shadow_shadowmapsampler;
866 extern int r_shadow_shadowmappcf;
867 qboolean R_CompileShader_CheckStaticParms(void)
868 {
869         static int r_compileshader_staticparms_save[1];
870         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
871         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
872
873         // detect all
874         if (r_glsl_saturation_redcompensate.integer)
875                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
876         if (r_glsl_vertextextureblend_usebothalphas.integer)
877                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
878         if (r_shadow_glossexact.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
880         if (r_glsl_postprocess.integer)
881         {
882                 if (r_glsl_postprocess_uservec1_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
884                 if (r_glsl_postprocess_uservec2_enable.integer)
885                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
886                 if (r_glsl_postprocess_uservec3_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
888                 if (r_glsl_postprocess_uservec4_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
890         }
891         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
893
894         if (r_shadow_shadowmapsampler)
895                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
896         if (r_shadow_shadowmappcf > 1)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
898         else if (r_shadow_shadowmappcf)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
900
901         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
902 }
903
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907         else \
908                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 {
911         shaderstaticparms_count = 0;
912
913         // emit all
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
925 }
926
927 /// information about each possible shader permutation
928 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
929 /// currently selected permutation
930 r_glsl_permutation_t *r_glsl_permutation;
931 /// storage for permutations linked in the hash table
932 memexpandablearray_t r_glsl_permutationarray;
933
934 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
935 {
936         //unsigned int hashdepth = 0;
937         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
938         r_glsl_permutation_t *p;
939         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
940         {
941                 if (p->mode == mode && p->permutation == permutation)
942                 {
943                         //if (hashdepth > 10)
944                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945                         return p;
946                 }
947                 //hashdepth++;
948         }
949         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
950         p->mode = mode;
951         p->permutation = permutation;
952         p->hashnext = r_glsl_permutationhash[mode][hashindex];
953         r_glsl_permutationhash[mode][hashindex] = p;
954         //if (hashdepth > 10)
955         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956         return p;
957 }
958
959 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
960 {
961         char *shaderstring;
962         if (!filename || !filename[0])
963                 return NULL;
964         if (!strcmp(filename, "glsl/default.glsl"))
965         {
966                 if (!glslshaderstring)
967                 {
968                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969                         if (glslshaderstring)
970                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
971                         else
972                                 glslshaderstring = (char *)builtinshaderstring;
973                 }
974                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
975                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
976                 return shaderstring;
977         }
978         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979         if (shaderstring)
980         {
981                 if (printfromdisknotice)
982                         Con_DPrintf("from disk %s... ", filename);
983                 return shaderstring;
984         }
985         return shaderstring;
986 }
987
988 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
989 {
990         int i;
991         int sampler;
992         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
993         char *vertexstring, *geometrystring, *fragmentstring;
994         char permutationname[256];
995         int vertstrings_count = 0;
996         int geomstrings_count = 0;
997         int fragstrings_count = 0;
998         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
999         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1000         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1001
1002         if (p->compiled)
1003                 return;
1004         p->compiled = true;
1005         p->program = 0;
1006
1007         permutationname[0] = 0;
1008         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1009         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1010         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1011
1012         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1013
1014         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1015         if(vid.support.gl20shaders130)
1016         {
1017                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1018                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1019                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1020                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1021                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1022                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1023         }
1024
1025         // the first pretext is which type of shader to compile as
1026         // (later these will all be bound together as a program object)
1027         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1028         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1029         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1030
1031         // the second pretext is the mode (for example a light source)
1032         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1033         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1034         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1035         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1036
1037         // now add all the permutation pretexts
1038         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1039         {
1040                 if (permutation & (1<<i))
1041                 {
1042                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1046                 }
1047                 else
1048                 {
1049                         // keep line numbers correct
1050                         vertstrings_list[vertstrings_count++] = "\n";
1051                         geomstrings_list[geomstrings_count++] = "\n";
1052                         fragstrings_list[fragstrings_count++] = "\n";
1053                 }
1054         }
1055
1056         // add static parms
1057         R_CompileShader_AddStaticParms(mode, permutation);
1058         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         vertstrings_count += shaderstaticparms_count;
1060         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061         geomstrings_count += shaderstaticparms_count;
1062         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1063         fragstrings_count += shaderstaticparms_count;
1064
1065         // now append the shader text itself
1066         vertstrings_list[vertstrings_count++] = vertexstring;
1067         geomstrings_list[geomstrings_count++] = geometrystring;
1068         fragstrings_list[fragstrings_count++] = fragmentstring;
1069
1070         // if any sources were NULL, clear the respective list
1071         if (!vertexstring)
1072                 vertstrings_count = 0;
1073         if (!geometrystring)
1074                 geomstrings_count = 0;
1075         if (!fragmentstring)
1076                 fragstrings_count = 0;
1077
1078         // compile the shader program
1079         if (vertstrings_count + geomstrings_count + fragstrings_count)
1080                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1081         if (p->program)
1082         {
1083                 CHECKGLERROR
1084                 qglUseProgram(p->program);CHECKGLERROR
1085                 // look up all the uniform variable names we care about, so we don't
1086                 // have to look them up every time we set them
1087
1088                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1089                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1090                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1091                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1092                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1093                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1094                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1095                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1096                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1097                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1098                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1099                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1100                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1101                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1102                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1103                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1104                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1105                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1106                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1107                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1108                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1109                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1110                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1111                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1112                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1113                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1114                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1115                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1116                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1117                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1118                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1119                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1120                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1121                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1122                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1123                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1124                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1125                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1126                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1127                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1128                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1129                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1130                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1131                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1132                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1133                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1134                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1135                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1136                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1137                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1138                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1139                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1140                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1141                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1142                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1143                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1144                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1145                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1146                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1147                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1148                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1149                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1150                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1153                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1156                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1157                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1158                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1159                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1160                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1161                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1162                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1163                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1164                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174                 // initialize the samplers to refer to the texture units we use
1175                 p->tex_Texture_First = -1;
1176                 p->tex_Texture_Second = -1;
1177                 p->tex_Texture_GammaRamps = -1;
1178                 p->tex_Texture_Normal = -1;
1179                 p->tex_Texture_Color = -1;
1180                 p->tex_Texture_Gloss = -1;
1181                 p->tex_Texture_Glow = -1;
1182                 p->tex_Texture_SecondaryNormal = -1;
1183                 p->tex_Texture_SecondaryColor = -1;
1184                 p->tex_Texture_SecondaryGloss = -1;
1185                 p->tex_Texture_SecondaryGlow = -1;
1186                 p->tex_Texture_Pants = -1;
1187                 p->tex_Texture_Shirt = -1;
1188                 p->tex_Texture_FogHeightTexture = -1;
1189                 p->tex_Texture_FogMask = -1;
1190                 p->tex_Texture_Lightmap = -1;
1191                 p->tex_Texture_Deluxemap = -1;
1192                 p->tex_Texture_Attenuation = -1;
1193                 p->tex_Texture_Cube = -1;
1194                 p->tex_Texture_Refraction = -1;
1195                 p->tex_Texture_Reflection = -1;
1196                 p->tex_Texture_ShadowMap2D = -1;
1197                 p->tex_Texture_CubeProjection = -1;
1198                 p->tex_Texture_ScreenNormalMap = -1;
1199                 p->tex_Texture_ScreenDiffuse = -1;
1200                 p->tex_Texture_ScreenSpecular = -1;
1201                 p->tex_Texture_ReflectMask = -1;
1202                 p->tex_Texture_ReflectCube = -1;
1203                 p->tex_Texture_BounceGrid = -1;
1204                 sampler = 0;
1205                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1206                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1207                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1208                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1209                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1210                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1211                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1216                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1217                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1218                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1219                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1220                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1221                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1222                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1223                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1224                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1225                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1226                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1227                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1231                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1232                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1233                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1234                 CHECKGLERROR
1235                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1236         }
1237         else
1238                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1239
1240         // free the strings
1241         if (vertexstring)
1242                 Mem_Free(vertexstring);
1243         if (geometrystring)
1244                 Mem_Free(geometrystring);
1245         if (fragmentstring)
1246                 Mem_Free(fragmentstring);
1247 }
1248
1249 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1250 {
1251         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1252         if (r_glsl_permutation != perm)
1253         {
1254                 r_glsl_permutation = perm;
1255                 if (!r_glsl_permutation->program)
1256                 {
1257                         if (!r_glsl_permutation->compiled)
1258                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                         if (!r_glsl_permutation->program)
1260                         {
1261                                 // remove features until we find a valid permutation
1262                                 int i;
1263                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1264                                 {
1265                                         // reduce i more quickly whenever it would not remove any bits
1266                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1267                                         if (!(permutation & j))
1268                                                 continue;
1269                                         permutation -= j;
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         if (!r_glsl_permutation->compiled)
1272                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1273                                         if (r_glsl_permutation->program)
1274                                                 break;
1275                                 }
1276                                 if (i >= SHADERPERMUTATION_COUNT)
1277                                 {
1278                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1279                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1280                                         qglUseProgram(0);CHECKGLERROR
1281                                         return; // no bit left to clear, entire mode is broken
1282                                 }
1283                         }
1284                 }
1285                 CHECKGLERROR
1286                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1287         }
1288         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1289         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1290         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1291 }
1292
1293 #ifdef SUPPORTD3D
1294
1295 #ifdef SUPPORTD3D
1296 #include <d3d9.h>
1297 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1298 extern D3DCAPS9 vid_d3d9caps;
1299 #endif
1300
1301 struct r_hlsl_permutation_s;
1302 typedef struct r_hlsl_permutation_s
1303 {
1304         /// hash lookup data
1305         struct r_hlsl_permutation_s *hashnext;
1306         unsigned int mode;
1307         unsigned int permutation;
1308
1309         /// indicates if we have tried compiling this permutation already
1310         qboolean compiled;
1311         /// NULL if compilation failed
1312         IDirect3DVertexShader9 *vertexshader;
1313         IDirect3DPixelShader9 *pixelshader;
1314 }
1315 r_hlsl_permutation_t;
1316
1317 typedef enum D3DVSREGISTER_e
1318 {
1319         D3DVSREGISTER_TexMatrix = 0, // float4x4
1320         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1321         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1322         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1323         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1324         D3DVSREGISTER_ModelToLight = 20, // float4x4
1325         D3DVSREGISTER_EyePosition = 24,
1326         D3DVSREGISTER_FogPlane = 25,
1327         D3DVSREGISTER_LightDir = 26,
1328         D3DVSREGISTER_LightPosition = 27,
1329 }
1330 D3DVSREGISTER_t;
1331
1332 typedef enum D3DPSREGISTER_e
1333 {
1334         D3DPSREGISTER_Alpha = 0,
1335         D3DPSREGISTER_BloomBlur_Parameters = 1,
1336         D3DPSREGISTER_ClientTime = 2,
1337         D3DPSREGISTER_Color_Ambient = 3,
1338         D3DPSREGISTER_Color_Diffuse = 4,
1339         D3DPSREGISTER_Color_Specular = 5,
1340         D3DPSREGISTER_Color_Glow = 6,
1341         D3DPSREGISTER_Color_Pants = 7,
1342         D3DPSREGISTER_Color_Shirt = 8,
1343         D3DPSREGISTER_DeferredColor_Ambient = 9,
1344         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1345         D3DPSREGISTER_DeferredColor_Specular = 11,
1346         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1347         D3DPSREGISTER_DeferredMod_Specular = 13,
1348         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1349         D3DPSREGISTER_EyePosition = 15, // unused
1350         D3DPSREGISTER_FogColor = 16,
1351         D3DPSREGISTER_FogHeightFade = 17,
1352         D3DPSREGISTER_FogPlane = 18,
1353         D3DPSREGISTER_FogPlaneViewDist = 19,
1354         D3DPSREGISTER_FogRangeRecip = 20,
1355         D3DPSREGISTER_LightColor = 21,
1356         D3DPSREGISTER_LightDir = 22, // unused
1357         D3DPSREGISTER_LightPosition = 23,
1358         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1359         D3DPSREGISTER_PixelSize = 25,
1360         D3DPSREGISTER_ReflectColor = 26,
1361         D3DPSREGISTER_ReflectFactor = 27,
1362         D3DPSREGISTER_ReflectOffset = 28,
1363         D3DPSREGISTER_RefractColor = 29,
1364         D3DPSREGISTER_Saturation = 30,
1365         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1366         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1367         D3DPSREGISTER_ScreenToDepth = 33,
1368         D3DPSREGISTER_ShadowMap_Parameters = 34,
1369         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1370         D3DPSREGISTER_SpecularPower = 36,
1371         D3DPSREGISTER_UserVec1 = 37,
1372         D3DPSREGISTER_UserVec2 = 38,
1373         D3DPSREGISTER_UserVec3 = 39,
1374         D3DPSREGISTER_UserVec4 = 40,
1375         D3DPSREGISTER_ViewTintColor = 41,
1376         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1377         D3DPSREGISTER_BloomColorSubtract = 43,
1378         D3DPSREGISTER_ViewToLight = 44, // float4x4
1379         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1380         D3DPSREGISTER_NormalmapScrollBlend = 52,
1381         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1382         D3DPSREGISTER_OffsetMapping_Bias = 54,
1383         // next at 54
1384 }
1385 D3DPSREGISTER_t;
1386
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1393
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1395 {
1396         //unsigned int hashdepth = 0;
1397         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398         r_hlsl_permutation_t *p;
1399         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1400         {
1401                 if (p->mode == mode && p->permutation == permutation)
1402                 {
1403                         //if (hashdepth > 10)
1404                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405                         return p;
1406                 }
1407                 //hashdepth++;
1408         }
1409         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1410         p->mode = mode;
1411         p->permutation = permutation;
1412         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413         r_hlsl_permutationhash[mode][hashindex] = p;
1414         //if (hashdepth > 10)
1415         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416         return p;
1417 }
1418
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1420 {
1421         char *shaderstring;
1422         if (!filename || !filename[0])
1423                 return NULL;
1424         if (!strcmp(filename, "hlsl/default.hlsl"))
1425         {
1426                 if (!hlslshaderstring)
1427                 {
1428                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429                         if (hlslshaderstring)
1430                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1431                         else
1432                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1433                 }
1434                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436                 return shaderstring;
1437         }
1438         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439         if (shaderstring)
1440         {
1441                 if (printfromdisknotice)
1442                         Con_DPrintf("from disk %s... ", filename);
1443                 return shaderstring;
1444         }
1445         return shaderstring;
1446 }
1447
1448 #include <d3dx9.h>
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1451
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1453 {
1454         DWORD *vsbin = NULL;
1455         DWORD *psbin = NULL;
1456         fs_offset_t vsbinsize;
1457         fs_offset_t psbinsize;
1458 //      IDirect3DVertexShader9 *vs = NULL;
1459 //      IDirect3DPixelShader9 *ps = NULL;
1460         ID3DXBuffer *vslog = NULL;
1461         ID3DXBuffer *vsbuffer = NULL;
1462         ID3DXConstantTable *vsconstanttable = NULL;
1463         ID3DXBuffer *pslog = NULL;
1464         ID3DXBuffer *psbuffer = NULL;
1465         ID3DXConstantTable *psconstanttable = NULL;
1466         int vsresult = 0;
1467         int psresult = 0;
1468         char temp[MAX_INPUTLINE];
1469         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470         char vabuf[1024];
1471         qboolean debugshader = gl_paranoid.integer != 0;
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474         if (!debugshader)
1475         {
1476                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1477                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1478         }
1479         if ((!vsbin && vertstring) || (!psbin && fragstring))
1480         {
1481                 const char* dllnames_d3dx9 [] =
1482                 {
1483                         "d3dx9_43.dll",
1484                         "d3dx9_42.dll",
1485                         "d3dx9_41.dll",
1486                         "d3dx9_40.dll",
1487                         "d3dx9_39.dll",
1488                         "d3dx9_38.dll",
1489                         "d3dx9_37.dll",
1490                         "d3dx9_36.dll",
1491                         "d3dx9_35.dll",
1492                         "d3dx9_34.dll",
1493                         "d3dx9_33.dll",
1494                         "d3dx9_32.dll",
1495                         "d3dx9_31.dll",
1496                         "d3dx9_30.dll",
1497                         "d3dx9_29.dll",
1498                         "d3dx9_28.dll",
1499                         "d3dx9_27.dll",
1500                         "d3dx9_26.dll",
1501                         "d3dx9_25.dll",
1502                         "d3dx9_24.dll",
1503                         NULL
1504                 };
1505                 dllhandle_t d3dx9_dll = NULL;
1506                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1507                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1508                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1509                 dllfunction_t d3dx9_dllfuncs[] =
1510                 {
1511                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1512                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1513                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1514                         {NULL, NULL}
1515                 };
1516                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1517                 {
1518                         DWORD shaderflags = 0;
1519                         if (debugshader)
1520                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1521                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1522                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1523                         if (vertstring && vertstring[0])
1524                         {
1525                                 if (debugshader)
1526                                 {
1527 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1528 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1529                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1530                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531                                 }
1532                                 else
1533                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1534                                 if (vsbuffer)
1535                                 {
1536                                         vsbinsize = vsbuffer->GetBufferSize();
1537                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1538                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1539                                         vsbuffer->Release();
1540                                 }
1541                                 if (vslog)
1542                                 {
1543                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1544                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1545                                         vslog->Release();
1546                                 }
1547                         }
1548                         if (fragstring && fragstring[0])
1549                         {
1550                                 if (debugshader)
1551                                 {
1552 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1553 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1554                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1555                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556                                 }
1557                                 else
1558                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1559                                 if (psbuffer)
1560                                 {
1561                                         psbinsize = psbuffer->GetBufferSize();
1562                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1563                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1564                                         psbuffer->Release();
1565                                 }
1566                                 if (pslog)
1567                                 {
1568                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1569                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1570                                         pslog->Release();
1571                                 }
1572                         }
1573                         Sys_UnloadLibrary(&d3dx9_dll);
1574                 }
1575                 else
1576                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1577         }
1578         if (vsbin && psbin)
1579         {
1580                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1581                 if (FAILED(vsresult))
1582                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1583                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1584                 if (FAILED(psresult))
1585                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1586         }
1587         // free the shader data
1588         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1589         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1590 }
1591
1592 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1593 {
1594         int i;
1595         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1596         int vertstring_length = 0;
1597         int geomstring_length = 0;
1598         int fragstring_length = 0;
1599         char *t;
1600         char *vertexstring, *geometrystring, *fragmentstring;
1601         char *vertstring, *geomstring, *fragstring;
1602         char permutationname[256];
1603         char cachename[256];
1604         int vertstrings_count = 0;
1605         int geomstrings_count = 0;
1606         int fragstrings_count = 0;
1607         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1608         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1609         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1610
1611         if (p->compiled)
1612                 return;
1613         p->compiled = true;
1614         p->vertexshader = NULL;
1615         p->pixelshader = NULL;
1616
1617         permutationname[0] = 0;
1618         cachename[0] = 0;
1619         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1620         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1621         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1622
1623         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1624         strlcat(cachename, "hlsl/", sizeof(cachename));
1625
1626         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1627         vertstrings_count = 0;
1628         geomstrings_count = 0;
1629         fragstrings_count = 0;
1630         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1631         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1632         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1633
1634         // the first pretext is which type of shader to compile as
1635         // (later these will all be bound together as a program object)
1636         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1637         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1638         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1639
1640         // the second pretext is the mode (for example a light source)
1641         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1642         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1643         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1644         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1645         strlcat(cachename, modeinfo->name, sizeof(cachename));
1646
1647         // now add all the permutation pretexts
1648         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1649         {
1650                 if (permutation & (1<<i))
1651                 {
1652                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1655                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1656                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1657                 }
1658                 else
1659                 {
1660                         // keep line numbers correct
1661                         vertstrings_list[vertstrings_count++] = "\n";
1662                         geomstrings_list[geomstrings_count++] = "\n";
1663                         fragstrings_list[fragstrings_count++] = "\n";
1664                 }
1665         }
1666
1667         // add static parms
1668         R_CompileShader_AddStaticParms(mode, permutation);
1669         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670         vertstrings_count += shaderstaticparms_count;
1671         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1672         geomstrings_count += shaderstaticparms_count;
1673         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1674         fragstrings_count += shaderstaticparms_count;
1675
1676         // replace spaces in the cachename with _ characters
1677         for (i = 0;cachename[i];i++)
1678                 if (cachename[i] == ' ')
1679                         cachename[i] = '_';
1680
1681         // now append the shader text itself
1682         vertstrings_list[vertstrings_count++] = vertexstring;
1683         geomstrings_list[geomstrings_count++] = geometrystring;
1684         fragstrings_list[fragstrings_count++] = fragmentstring;
1685
1686         // if any sources were NULL, clear the respective list
1687         if (!vertexstring)
1688                 vertstrings_count = 0;
1689         if (!geometrystring)
1690                 geomstrings_count = 0;
1691         if (!fragmentstring)
1692                 fragstrings_count = 0;
1693
1694         vertstring_length = 0;
1695         for (i = 0;i < vertstrings_count;i++)
1696                 vertstring_length += strlen(vertstrings_list[i]);
1697         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1698         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1699                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1700
1701         geomstring_length = 0;
1702         for (i = 0;i < geomstrings_count;i++)
1703                 geomstring_length += strlen(geomstrings_list[i]);
1704         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1705         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1706                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1707
1708         fragstring_length = 0;
1709         for (i = 0;i < fragstrings_count;i++)
1710                 fragstring_length += strlen(fragstrings_list[i]);
1711         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1712         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1713                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1714
1715         // try to load the cached shader, or generate one
1716         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1717
1718         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1719                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1720         else
1721                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1722
1723         // free the strings
1724         if (vertstring)
1725                 Mem_Free(vertstring);
1726         if (geomstring)
1727                 Mem_Free(geomstring);
1728         if (fragstring)
1729                 Mem_Free(fragstring);
1730         if (vertexstring)
1731                 Mem_Free(vertexstring);
1732         if (geometrystring)
1733                 Mem_Free(geometrystring);
1734         if (fragmentstring)
1735                 Mem_Free(fragmentstring);
1736 }
1737
1738 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1744
1745 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1746 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1747 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1748 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1749 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1750 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1751
1752 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1753 {
1754         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1755         if (r_hlsl_permutation != perm)
1756         {
1757                 r_hlsl_permutation = perm;
1758                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759                 {
1760                         if (!r_hlsl_permutation->compiled)
1761                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1762                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1763                         {
1764                                 // remove features until we find a valid permutation
1765                                 int i;
1766                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1767                                 {
1768                                         // reduce i more quickly whenever it would not remove any bits
1769                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1770                                         if (!(permutation & j))
1771                                                 continue;
1772                                         permutation -= j;
1773                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1774                                         if (!r_hlsl_permutation->compiled)
1775                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1776                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1777                                                 break;
1778                                 }
1779                                 if (i >= SHADERPERMUTATION_COUNT)
1780                                 {
1781                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1782                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783                                         return; // no bit left to clear, entire mode is broken
1784                                 }
1785                         }
1786                 }
1787                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1788                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1789         }
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1791         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1792         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1793 }
1794 #endif
1795
1796 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1797 {
1798         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1800         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1801         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1802 }
1803
1804 void R_GLSL_Restart_f(void)
1805 {
1806         unsigned int i, limit;
1807         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1808                 Mem_Free(glslshaderstring);
1809         glslshaderstring = NULL;
1810         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1811                 Mem_Free(hlslshaderstring);
1812         hlslshaderstring = NULL;
1813         switch(vid.renderpath)
1814         {
1815         case RENDERPATH_D3D9:
1816 #ifdef SUPPORTD3D
1817                 {
1818                         r_hlsl_permutation_t *p;
1819                         r_hlsl_permutation = NULL;
1820                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1821                         for (i = 0;i < limit;i++)
1822                         {
1823                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1824                                 {
1825                                         if (p->vertexshader)
1826                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1827                                         if (p->pixelshader)
1828                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1829                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1830                                 }
1831                         }
1832                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1833                 }
1834 #endif
1835                 break;
1836         case RENDERPATH_D3D10:
1837                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838                 break;
1839         case RENDERPATH_D3D11:
1840                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1841                 break;
1842         case RENDERPATH_GL20:
1843         case RENDERPATH_GLES2:
1844                 {
1845                         r_glsl_permutation_t *p;
1846                         r_glsl_permutation = NULL;
1847                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1848                         for (i = 0;i < limit;i++)
1849                         {
1850                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1851                                 {
1852                                         GL_Backend_FreeProgram(p->program);
1853                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1854                                 }
1855                         }
1856                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1857                 }
1858                 break;
1859         case RENDERPATH_GL11:
1860         case RENDERPATH_GL13:
1861         case RENDERPATH_GLES1:
1862                 break;
1863         case RENDERPATH_SOFT:
1864                 break;
1865         }
1866 }
1867
1868 static void R_GLSL_DumpShader_f(void)
1869 {
1870         int i;
1871         qfile_t *file;
1872
1873         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1874         if (file)
1875         {
1876                 FS_Print(file, "/* The engine may define the following macros:\n");
1877                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1878                 for (i = 0;i < SHADERMODE_COUNT;i++)
1879                         FS_Print(file, glslshadermodeinfo[i].pretext);
1880                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1881                         FS_Print(file, shaderpermutationinfo[i].pretext);
1882                 FS_Print(file, "*/\n");
1883                 FS_Print(file, builtinshaderstring);
1884                 FS_Close(file);
1885                 Con_Printf("glsl/default.glsl written\n");
1886         }
1887         else
1888                 Con_Printf("failed to write to glsl/default.glsl\n");
1889
1890         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1891         if (file)
1892         {
1893                 FS_Print(file, "/* The engine may define the following macros:\n");
1894                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1895                 for (i = 0;i < SHADERMODE_COUNT;i++)
1896                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1897                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1898                         FS_Print(file, shaderpermutationinfo[i].pretext);
1899                 FS_Print(file, "*/\n");
1900                 FS_Print(file, builtinhlslshaderstring);
1901                 FS_Close(file);
1902                 Con_Printf("hlsl/default.hlsl written\n");
1903         }
1904         else
1905                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1906 }
1907
1908 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1909 {
1910         unsigned int permutation = 0;
1911         if (r_trippy.integer && !notrippy)
1912                 permutation |= SHADERPERMUTATION_TRIPPY;
1913         permutation |= SHADERPERMUTATION_VIEWTINT;
1914         if (first)
1915                 permutation |= SHADERPERMUTATION_DIFFUSE;
1916         if (second)
1917                 permutation |= SHADERPERMUTATION_SPECULAR;
1918         if (texturemode == GL_MODULATE)
1919                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1920         else if (texturemode == GL_ADD)
1921                 permutation |= SHADERPERMUTATION_GLOW;
1922         else if (texturemode == GL_DECAL)
1923                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1924         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1925                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1926         if (suppresstexalpha)
1927                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1928         if (!second)
1929                 texturemode = GL_MODULATE;
1930         if (vid.allowalphatocoverage)
1931                 GL_AlphaToCoverage(false);
1932         switch (vid.renderpath)
1933         {
1934         case RENDERPATH_D3D9:
1935 #ifdef SUPPORTD3D
1936                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1937                 R_Mesh_TexBind(GL20TU_FIRST , first );
1938                 R_Mesh_TexBind(GL20TU_SECOND, second);
1939                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1940                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1941 #endif
1942                 break;
1943         case RENDERPATH_D3D10:
1944                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945                 break;
1946         case RENDERPATH_D3D11:
1947                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_GL20:
1950         case RENDERPATH_GLES2:
1951                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1952                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1953                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1954                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1955                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1956                 break;
1957         case RENDERPATH_GL13:
1958         case RENDERPATH_GLES1:
1959                 R_Mesh_TexBind(0, first );
1960                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1961                 R_Mesh_TexBind(1, second);
1962                 if (second)
1963                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1964                 break;
1965         case RENDERPATH_GL11:
1966                 R_Mesh_TexBind(0, first );
1967                 break;
1968         case RENDERPATH_SOFT:
1969                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1970                 R_Mesh_TexBind(GL20TU_FIRST , first );
1971                 R_Mesh_TexBind(GL20TU_SECOND, second);
1972                 break;
1973         }
1974 }
1975
1976 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1977 {
1978         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1979 }
1980
1981 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1982 {
1983         unsigned int permutation = 0;
1984         if (r_trippy.integer && !notrippy)
1985                 permutation |= SHADERPERMUTATION_TRIPPY;
1986         if (depthrgb)
1987                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1988         if (vid.allowalphatocoverage)
1989                 GL_AlphaToCoverage(false);
1990         switch (vid.renderpath)
1991         {
1992         case RENDERPATH_D3D9:
1993 #ifdef SUPPORTD3D
1994                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995 #endif
1996                 break;
1997         case RENDERPATH_D3D10:
1998                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999                 break;
2000         case RENDERPATH_D3D11:
2001                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002                 break;
2003         case RENDERPATH_GL20:
2004         case RENDERPATH_GLES2:
2005                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006                 break;
2007         case RENDERPATH_GL13:
2008         case RENDERPATH_GLES1:
2009                 R_Mesh_TexBind(0, 0);
2010                 R_Mesh_TexBind(1, 0);
2011                 break;
2012         case RENDERPATH_GL11:
2013                 R_Mesh_TexBind(0, 0);
2014                 break;
2015         case RENDERPATH_SOFT:
2016                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         }
2019 }
2020
2021 void R_SetupShader_ShowDepth(qboolean notrippy)
2022 {
2023         int permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         if (vid.allowalphatocoverage)
2027                 GL_AlphaToCoverage(false);
2028         switch (vid.renderpath)
2029         {
2030         case RENDERPATH_D3D9:
2031 #ifdef SUPPORTHLSL
2032                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2033 #endif
2034                 break;
2035         case RENDERPATH_D3D10:
2036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037                 break;
2038         case RENDERPATH_D3D11:
2039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040                 break;
2041         case RENDERPATH_GL20:
2042         case RENDERPATH_GLES2:
2043                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2044                 break;
2045         case RENDERPATH_GL13:
2046         case RENDERPATH_GLES1:
2047                 break;
2048         case RENDERPATH_GL11:
2049                 break;
2050         case RENDERPATH_SOFT:
2051                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2052                 break;
2053         }
2054 }
2055
2056 extern qboolean r_shadow_usingdeferredprepass;
2057 extern rtexture_t *r_shadow_attenuationgradienttexture;
2058 extern rtexture_t *r_shadow_attenuation2dtexture;
2059 extern rtexture_t *r_shadow_attenuation3dtexture;
2060 extern qboolean r_shadow_usingshadowmap2d;
2061 extern qboolean r_shadow_usingshadowmaportho;
2062 extern float r_shadow_shadowmap_texturescale[2];
2063 extern float r_shadow_shadowmap_parameters[4];
2064 extern qboolean r_shadow_shadowmapvsdct;
2065 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2066 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2067 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2068 extern matrix4x4_t r_shadow_shadowmapmatrix;
2069 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2070 extern int r_shadow_prepass_width;
2071 extern int r_shadow_prepass_height;
2072 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2073 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2074 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2075 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2076
2077 #define BLENDFUNC_ALLOWS_COLORMOD      1
2078 #define BLENDFUNC_ALLOWS_FOG           2
2079 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2080 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2081 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2082 static int R_BlendFuncFlags(int src, int dst)
2083 {
2084         int r = 0;
2085
2086         // a blendfunc allows colormod if:
2087         // a) it can never keep the destination pixel invariant, or
2088         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2089         // this is to prevent unintended side effects from colormod
2090
2091         // a blendfunc allows fog if:
2092         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2093         // this is to prevent unintended side effects from fog
2094
2095         // these checks are the output of fogeval.pl
2096
2097         r |= BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2107         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2109         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2112         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119
2120         return r;
2121 }
2122
2123 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2124 {
2125         // select a permutation of the lighting shader appropriate to this
2126         // combination of texture, entity, light source, and fogging, only use the
2127         // minimum features necessary to avoid wasting rendering time in the
2128         // fragment shader on features that are not being used
2129         unsigned int permutation = 0;
2130         unsigned int mode = 0;
2131         int blendfuncflags;
2132         static float dummy_colormod[3] = {1, 1, 1};
2133         float *colormod = rsurface.colormod;
2134         float m16f[16];
2135         matrix4x4_t tempmatrix;
2136         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2137         if (r_trippy.integer && !notrippy)
2138                 permutation |= SHADERPERMUTATION_TRIPPY;
2139         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2140                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2141         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2142                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2143         if (rsurfacepass == RSURFPASS_BACKGROUND)
2144         {
2145                 // distorted background
2146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2147                 {
2148                         mode = SHADERMODE_WATER;
2149                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2150                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2151                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2152                         {
2153                                 // this is the right thing to do for wateralpha
2154                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2155                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2156                         }
2157                         else
2158                         {
2159                                 // this is the right thing to do for entity alpha
2160                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162                         }
2163                 }
2164                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2165                 {
2166                         mode = SHADERMODE_REFRACTION;
2167                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2168                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                 }
2172                 else
2173                 {
2174                         mode = SHADERMODE_GENERIC;
2175                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2176                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2177                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2178                 }
2179                 if (vid.allowalphatocoverage)
2180                         GL_AlphaToCoverage(false);
2181         }
2182         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2183         {
2184                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2185                 {
2186                         switch(rsurface.texture->offsetmapping)
2187                         {
2188                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2189                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191                         case OFFSETMAPPING_OFF: break;
2192                         }
2193                 }
2194                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196                 // normalmap (deferred prepass), may use alpha test on diffuse
2197                 mode = SHADERMODE_DEFERREDGEOMETRY;
2198                 GL_BlendFunc(GL_ONE, GL_ZERO);
2199                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2200                 if (vid.allowalphatocoverage)
2201                         GL_AlphaToCoverage(false);
2202         }
2203         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2204         {
2205                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2206                 {
2207                         switch(rsurface.texture->offsetmapping)
2208                         {
2209                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2210                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2212                         case OFFSETMAPPING_OFF: break;
2213                         }
2214                 }
2215                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2216                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2217                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2218                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2219                 // light source
2220                 mode = SHADERMODE_LIGHTSOURCE;
2221                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2222                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2223                 if (diffusescale > 0)
2224                         permutation |= SHADERPERMUTATION_DIFFUSE;
2225                 if (specularscale > 0)
2226                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2227                 if (r_refdef.fogenabled)
2228                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2229                 if (rsurface.texture->colormapping)
2230                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2231                 if (r_shadow_usingshadowmap2d)
2232                 {
2233                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2234                         if(r_shadow_shadowmapvsdct)
2235                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2236
2237                         if (r_shadow_shadowmap2ddepthbuffer)
2238                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2239                 }
2240                 if (rsurface.texture->reflectmasktexture)
2241                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2242                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2243                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2244                 if (vid.allowalphatocoverage)
2245                         GL_AlphaToCoverage(false);
2246         }
2247         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2248         {
2249                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2250                 {
2251                         switch(rsurface.texture->offsetmapping)
2252                         {
2253                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2254                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2256                         case OFFSETMAPPING_OFF: break;
2257                         }
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2262                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2263                 // unshaded geometry (fullbright or ambient model lighting)
2264                 mode = SHADERMODE_FLATCOLOR;
2265                 ambientscale = diffusescale = specularscale = 0;
2266                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2267                         permutation |= SHADERPERMUTATION_GLOW;
2268                 if (r_refdef.fogenabled)
2269                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270                 if (rsurface.texture->colormapping)
2271                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2272                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273                 {
2274                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276
2277                         if (r_shadow_shadowmap2ddepthbuffer)
2278                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2279                 }
2280                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2281                         permutation |= SHADERPERMUTATION_REFLECTION;
2282                 if (rsurface.texture->reflectmasktexture)
2283                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286                 // when using alphatocoverage, we don't need alphakill
2287                 if (vid.allowalphatocoverage)
2288                 {
2289                         if (r_transparent_alphatocoverage.integer)
2290                         {
2291                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2292                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2293                         }
2294                         else
2295                                 GL_AlphaToCoverage(false);
2296                 }
2297         }
2298         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2299         {
2300                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2301                 {
2302                         switch(rsurface.texture->offsetmapping)
2303                         {
2304                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2305                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2307                         case OFFSETMAPPING_OFF: break;
2308                         }
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2311                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2313                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2314                 // directional model lighting
2315                 mode = SHADERMODE_LIGHTDIRECTION;
2316                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2317                         permutation |= SHADERPERMUTATION_GLOW;
2318                 permutation |= SHADERPERMUTATION_DIFFUSE;
2319                 if (specularscale > 0)
2320                         permutation |= SHADERPERMUTATION_SPECULAR;
2321                 if (r_refdef.fogenabled)
2322                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2323                 if (rsurface.texture->colormapping)
2324                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2325                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2326                 {
2327                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2328                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2329
2330                         if (r_shadow_shadowmap2ddepthbuffer)
2331                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2332                 }
2333                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2334                         permutation |= SHADERPERMUTATION_REFLECTION;
2335                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2336                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2337                 if (rsurface.texture->reflectmasktexture)
2338                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2339                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2340                 {
2341                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2342                         if (r_shadow_bouncegriddirectional)
2343                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2344                 }
2345                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2347                 // when using alphatocoverage, we don't need alphakill
2348                 if (vid.allowalphatocoverage)
2349                 {
2350                         if (r_transparent_alphatocoverage.integer)
2351                         {
2352                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2353                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2354                         }
2355                         else
2356                                 GL_AlphaToCoverage(false);
2357                 }
2358         }
2359         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2360         {
2361                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2362                 {
2363                         switch(rsurface.texture->offsetmapping)
2364                         {
2365                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2366                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2367                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2368                         case OFFSETMAPPING_OFF: break;
2369                         }
2370                 }
2371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2372                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2374                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2375                 // ambient model lighting
2376                 mode = SHADERMODE_LIGHTDIRECTION;
2377                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2378                         permutation |= SHADERPERMUTATION_GLOW;
2379                 if (r_refdef.fogenabled)
2380                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2381                 if (rsurface.texture->colormapping)
2382                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2383                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2384                 {
2385                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2386                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2387
2388                         if (r_shadow_shadowmap2ddepthbuffer)
2389                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2390                 }
2391                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2392                         permutation |= SHADERPERMUTATION_REFLECTION;
2393                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2394                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2395                 if (rsurface.texture->reflectmasktexture)
2396                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2397                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2398                 {
2399                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2400                         if (r_shadow_bouncegriddirectional)
2401                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2402                 }
2403                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2404                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2405                 // when using alphatocoverage, we don't need alphakill
2406                 if (vid.allowalphatocoverage)
2407                 {
2408                         if (r_transparent_alphatocoverage.integer)
2409                         {
2410                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2411                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2412                         }
2413                         else
2414                                 GL_AlphaToCoverage(false);
2415                 }
2416         }
2417         else
2418         {
2419                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2420                 {
2421                         switch(rsurface.texture->offsetmapping)
2422                         {
2423                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2424                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2425                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2426                         case OFFSETMAPPING_OFF: break;
2427                         }
2428                 }
2429                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2430                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2431                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2432                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2433                 // lightmapped wall
2434                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2435                         permutation |= SHADERPERMUTATION_GLOW;
2436                 if (r_refdef.fogenabled)
2437                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2438                 if (rsurface.texture->colormapping)
2439                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2440                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2441                 {
2442                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2443                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2444
2445                         if (r_shadow_shadowmap2ddepthbuffer)
2446                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2447                 }
2448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2449                         permutation |= SHADERPERMUTATION_REFLECTION;
2450                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2451                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2452                 if (rsurface.texture->reflectmasktexture)
2453                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2454                 if (FAKELIGHT_ENABLED)
2455                 {
2456                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2457                         mode = SHADERMODE_FAKELIGHT;
2458                         permutation |= SHADERPERMUTATION_DIFFUSE;
2459                         if (specularscale > 0)
2460                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2461                 }
2462                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2463                 {
2464                         // deluxemapping (light direction texture)
2465                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2466                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2467                         else
2468                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2469                         permutation |= SHADERPERMUTATION_DIFFUSE;
2470                         if (specularscale > 0)
2471                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472                 }
2473                 else if (r_glsl_deluxemapping.integer >= 2)
2474                 {
2475                         // fake deluxemapping (uniform light direction in tangentspace)
2476                         if (rsurface.uselightmaptexture)
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2478                         else
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2480                         permutation |= SHADERPERMUTATION_DIFFUSE;
2481                         if (specularscale > 0)
2482                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483                 }
2484                 else if (rsurface.uselightmaptexture)
2485                 {
2486                         // ordinary lightmapping (q1bsp, q3bsp)
2487                         mode = SHADERMODE_LIGHTMAP;
2488                 }
2489                 else
2490                 {
2491                         // ordinary vertex coloring (q3bsp)
2492                         mode = SHADERMODE_VERTEXCOLOR;
2493                 }
2494                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2495                 {
2496                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2497                         if (r_shadow_bouncegriddirectional)
2498                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2499                 }
2500                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502                 // when using alphatocoverage, we don't need alphakill
2503                 if (vid.allowalphatocoverage)
2504                 {
2505                         if (r_transparent_alphatocoverage.integer)
2506                         {
2507                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2508                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2509                         }
2510                         else
2511                                 GL_AlphaToCoverage(false);
2512                 }
2513         }
2514         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2515                 colormod = dummy_colormod;
2516         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2517                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2518         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2519                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2520         switch(vid.renderpath)
2521         {
2522         case RENDERPATH_D3D9:
2523 #ifdef SUPPORTD3D
2524                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2525                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2526                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2527                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2531                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                 }
2533                 else
2534                 {
2535                         if (mode == SHADERMODE_LIGHTDIRECTION)
2536                         {
2537                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2538                         }
2539                 }
2540                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2542                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2543                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2544                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2545
2546                 if (mode == SHADERMODE_LIGHTSOURCE)
2547                 {
2548                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2549                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2552                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2553
2554                         // additive passes are only darkened by fog, not tinted
2555                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2556                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2557                 }
2558                 else
2559                 {
2560                         if (mode == SHADERMODE_FLATCOLOR)
2561                         {
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2563                         }
2564                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2565                         {
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2573                         }
2574                         else
2575                         {
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2581                         }
2582                         // additive passes are only darkened by fog, not tinted
2583                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2585                         else
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2587                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2591                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2594                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2595                         if (mode == SHADERMODE_WATER)
2596                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2597                 }
2598                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2600                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2601                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2602                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2603                 if (rsurface.texture->pantstexture)
2604                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2605                 else
2606                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2607                 if (rsurface.texture->shirttexture)
2608                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2609                 else
2610                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2611                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2615                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2616                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2617                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2620                         );
2621                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2623                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2624                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2625
2626                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2627                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2628                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2629                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2630                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2631                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2632                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2633                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2634                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2635                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2636                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2637                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2638                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2639                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2640                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2641                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2642                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2643                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2644                 {
2645                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2646                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2647                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2648                 }
2649                 else
2650                 {
2651                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2652                 }
2653 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2654                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2655                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2656                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2657                 {
2658                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2659                         if (rsurface.rtlight)
2660                         {
2661                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2662                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2663                         }
2664                 }
2665 #endif
2666                 break;
2667         case RENDERPATH_D3D10:
2668                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2669                 break;
2670         case RENDERPATH_D3D11:
2671                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2672                 break;
2673         case RENDERPATH_GL20:
2674         case RENDERPATH_GLES2:
2675                 if (!vid.useinterleavedarrays)
2676                 {
2677                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2678                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2679                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2683                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2684                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2685                 }
2686                 else
2687                 {
2688                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2689                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2690                 }
2691                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2692                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2693                 if (mode == SHADERMODE_LIGHTSOURCE)
2694                 {
2695                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2696                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2697                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2698                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2699                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2700                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2701         
2702                         // additive passes are only darkened by fog, not tinted
2703                         if (r_glsl_permutation->loc_FogColor >= 0)
2704                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2705                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2706                 }
2707                 else
2708                 {
2709                         if (mode == SHADERMODE_FLATCOLOR)
2710                         {
2711                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2712                         }
2713                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2714                         {
2715                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2716                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2717                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2718                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2719                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2720                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2721                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2722                         }
2723                         else
2724                         {
2725                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2726                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2727                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2730                         }
2731                         // additive passes are only darkened by fog, not tinted
2732                         if (r_glsl_permutation->loc_FogColor >= 0)
2733                         {
2734                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2735                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2736                                 else
2737                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2738                         }
2739                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2740                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2741                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2742                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2743                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2744                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2745                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2746                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2747                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2748                 }
2749                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2751                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2752                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2753                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2754
2755                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2756                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2757                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2758                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2759                 {
2760                         if (rsurface.texture->pantstexture)
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2762                         else
2763                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2764                 }
2765                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2766                 {
2767                         if (rsurface.texture->shirttexture)
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2769                         else
2770                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2771                 }
2772                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2773                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2774                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2775                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2776                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2777                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2778                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2780                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2781                         );
2782                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2783                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2784                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2785                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2786                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2787                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2788
2789                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2790                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2791                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2792                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2793                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2794                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2795                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2796                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2797                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2798                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2799                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2800                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2801                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2802                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2803                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2804                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2805                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2806                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2807                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2808                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2809                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2810                 {
2811                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2812                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2813                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2814                 }
2815                 else
2816                 {
2817                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2818                 }
2819                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2820                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2821                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2822                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2823                 {
2824                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2825                         if (rsurface.rtlight)
2826                         {
2827                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2828                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2829                         }
2830                 }
2831                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2832                 CHECKGLERROR
2833                 break;
2834         case RENDERPATH_GL11:
2835         case RENDERPATH_GL13:
2836         case RENDERPATH_GLES1:
2837                 break;
2838         case RENDERPATH_SOFT:
2839                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2840                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2841                 R_SetupShader_SetPermutationSoft(mode, permutation);
2842                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2843                 if (mode == SHADERMODE_LIGHTSOURCE)
2844                 {
2845                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2850                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2851         
2852                         // additive passes are only darkened by fog, not tinted
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2854                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2855                 }
2856                 else
2857                 {
2858                         if (mode == SHADERMODE_FLATCOLOR)
2859                         {
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2861                         }
2862                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2863                         {
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2871                         }
2872                         else
2873                         {
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2879                         }
2880                         // additive passes are only darkened by fog, not tinted
2881                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2883                         else
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2885                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2886                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2887                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2888                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2889                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2890                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2892                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2893                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2894                 }
2895                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2896                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2897                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2898                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2899                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2900
2901                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2902                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2903                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2904                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2905                 {
2906                         if (rsurface.texture->pantstexture)
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2908                         else
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2910                 }
2911                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2912                 {
2913                         if (rsurface.texture->shirttexture)
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2915                         else
2916                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2917                 }
2918                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2919                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2920                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2921                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2922                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2923                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2924                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2925                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2926                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2927                         );
2928                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2930                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2931                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2932
2933                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2934                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2935                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2936                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2937                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2938                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2939                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2940                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2941                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2942                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2943                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2944                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2945                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2946                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2947                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2948                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2949                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2950                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2951                 {
2952                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2953                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2954                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2955                 }
2956                 else
2957                 {
2958                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2959                 }
2960 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2961                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2962                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2963                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2964                 {
2965                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2966                         if (rsurface.rtlight)
2967                         {
2968                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2969                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2970                         }
2971                 }
2972                 break;
2973         }
2974 }
2975
2976 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2977 {
2978         // select a permutation of the lighting shader appropriate to this
2979         // combination of texture, entity, light source, and fogging, only use the
2980         // minimum features necessary to avoid wasting rendering time in the
2981         // fragment shader on features that are not being used
2982         unsigned int permutation = 0;
2983         unsigned int mode = 0;
2984         const float *lightcolorbase = rtlight->currentcolor;
2985         float ambientscale = rtlight->ambientscale;
2986         float diffusescale = rtlight->diffusescale;
2987         float specularscale = rtlight->specularscale;
2988         // this is the location of the light in view space
2989         vec3_t viewlightorigin;
2990         // this transforms from view space (camera) to light space (cubemap)
2991         matrix4x4_t viewtolight;
2992         matrix4x4_t lighttoview;
2993         float viewtolight16f[16];
2994         // light source
2995         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2996         if (rtlight->currentcubemap != r_texture_whitecube)
2997                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2998         if (diffusescale > 0)
2999                 permutation |= SHADERPERMUTATION_DIFFUSE;
3000         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3001                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3002         if (r_shadow_usingshadowmap2d)
3003         {
3004                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3005                 if (r_shadow_shadowmapvsdct)
3006                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3007
3008                 if (r_shadow_shadowmap2ddepthbuffer)
3009                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3010         }
3011         if (vid.allowalphatocoverage)
3012                 GL_AlphaToCoverage(false);
3013         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3014         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3015         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3016         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3017         switch(vid.renderpath)
3018         {
3019         case RENDERPATH_D3D9:
3020 #ifdef SUPPORTD3D
3021                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3022                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3023                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3027                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3028                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3029                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3030                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3031                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3032
3033                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3034                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3035                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3036                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3037                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3038 #endif
3039                 break;
3040         case RENDERPATH_D3D10:
3041                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3042                 break;
3043         case RENDERPATH_D3D11:
3044                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3045                 break;
3046         case RENDERPATH_GL20:
3047         case RENDERPATH_GLES2:
3048                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3049                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3050                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3051                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3052                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3053                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3054                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3055                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3056                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3057                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3058                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3059
3060                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3061                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3062                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3063                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3064                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3065                 break;
3066         case RENDERPATH_GL11:
3067         case RENDERPATH_GL13:
3068         case RENDERPATH_GLES1:
3069                 break;
3070         case RENDERPATH_SOFT:
3071                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3072                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3073                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3074                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3077                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3078                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3079                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3080                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3081                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3082
3083                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3084                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3085                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3086                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3087                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3088                 break;
3089         }
3090 }
3091
3092 #define SKINFRAME_HASH 1024
3093
3094 typedef struct
3095 {
3096         int loadsequence; // incremented each level change
3097         memexpandablearray_t array;
3098         skinframe_t *hash[SKINFRAME_HASH];
3099 }
3100 r_skinframe_t;
3101 r_skinframe_t r_skinframe;
3102
3103 void R_SkinFrame_PrepareForPurge(void)
3104 {
3105         r_skinframe.loadsequence++;
3106         // wrap it without hitting zero
3107         if (r_skinframe.loadsequence >= 200)
3108                 r_skinframe.loadsequence = 1;
3109 }
3110
3111 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3112 {
3113         if (!skinframe)
3114                 return;
3115         // mark the skinframe as used for the purging code
3116         skinframe->loadsequence = r_skinframe.loadsequence;
3117 }
3118
3119 void R_SkinFrame_Purge(void)
3120 {
3121         int i;
3122         skinframe_t *s;
3123         for (i = 0;i < SKINFRAME_HASH;i++)
3124         {
3125                 for (s = r_skinframe.hash[i];s;s = s->next)
3126                 {
3127                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3128                         {
3129                                 if (s->merged == s->base)
3130                                         s->merged = NULL;
3131                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3132                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3133                                 R_PurgeTexture(s->merged);s->merged = NULL;
3134                                 R_PurgeTexture(s->base  );s->base   = NULL;
3135                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3136                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3137                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3138                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3139                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3140                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3141                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3142                                 s->loadsequence = 0;
3143                         }
3144                 }
3145         }
3146 }
3147
3148 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3149         skinframe_t *item;
3150         char basename[MAX_QPATH];
3151
3152         Image_StripImageExtension(name, basename, sizeof(basename));
3153
3154         if( last == NULL ) {
3155                 int hashindex;
3156                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3157                 item = r_skinframe.hash[hashindex];
3158         } else {
3159                 item = last->next;
3160         }
3161
3162         // linearly search through the hash bucket
3163         for( ; item ; item = item->next ) {
3164                 if( !strcmp( item->basename, basename ) ) {
3165                         return item;
3166                 }
3167         }
3168         return NULL;
3169 }
3170
3171 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3172 {
3173         skinframe_t *item;
3174         int hashindex;
3175         char basename[MAX_QPATH];
3176
3177         Image_StripImageExtension(name, basename, sizeof(basename));
3178
3179         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3180         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3181                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3182                         break;
3183
3184         if (!item) {
3185                 rtexture_t *dyntexture;
3186                 // check whether its a dynamic texture
3187                 dyntexture = CL_GetDynTexture( basename );
3188                 if (!add && !dyntexture)
3189                         return NULL;
3190                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3191                 memset(item, 0, sizeof(*item));
3192                 strlcpy(item->basename, basename, sizeof(item->basename));
3193                 item->base = dyntexture; // either NULL or dyntexture handle
3194                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3195                 item->comparewidth = comparewidth;
3196                 item->compareheight = compareheight;
3197                 item->comparecrc = comparecrc;
3198                 item->next = r_skinframe.hash[hashindex];
3199                 r_skinframe.hash[hashindex] = item;
3200         }
3201         else if (textureflags & TEXF_FORCE_RELOAD)
3202         {
3203                 rtexture_t *dyntexture;
3204                 // check whether its a dynamic texture
3205                 dyntexture = CL_GetDynTexture( basename );
3206                 if (!add && !dyntexture)
3207                         return NULL;
3208                 if (item->merged == item->base)
3209                         item->merged = NULL;
3210                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3211                 R_PurgeTexture(item->stain );item->stain  = NULL;
3212                 R_PurgeTexture(item->merged);item->merged = NULL;
3213                 R_PurgeTexture(item->base  );item->base   = NULL;
3214                 R_PurgeTexture(item->pants );item->pants  = NULL;
3215                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3216                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3217                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3218                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3219                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3220         R_PurgeTexture(item->reflect);item->reflect = NULL;
3221                 item->loadsequence = 0;
3222         }
3223         else if( item->base == NULL )
3224         {
3225                 rtexture_t *dyntexture;
3226                 // check whether its a dynamic texture
3227                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3228                 dyntexture = CL_GetDynTexture( basename );
3229                 item->base = dyntexture; // either NULL or dyntexture handle
3230         }
3231
3232         R_SkinFrame_MarkUsed(item);
3233         return item;
3234 }
3235
3236 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3237         { \
3238                 unsigned long long avgcolor[5], wsum; \
3239                 int pix, comp, w; \
3240                 avgcolor[0] = 0; \
3241                 avgcolor[1] = 0; \
3242                 avgcolor[2] = 0; \
3243                 avgcolor[3] = 0; \
3244                 avgcolor[4] = 0; \
3245                 wsum = 0; \
3246                 for(pix = 0; pix < cnt; ++pix) \
3247                 { \
3248                         w = 0; \
3249                         for(comp = 0; comp < 3; ++comp) \
3250                                 w += getpixel; \
3251                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3252                         { \
3253                                 ++wsum; \
3254                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3255                                 w = getpixel; \
3256                                 for(comp = 0; comp < 3; ++comp) \
3257                                         avgcolor[comp] += getpixel * w; \
3258                                 avgcolor[3] += w; \
3259                         } \
3260                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3261                         avgcolor[4] += getpixel; \
3262                 } \
3263                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3264                         avgcolor[3] = 1; \
3265                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3266                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3267                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3268                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3269         }
3270
3271 extern cvar_t gl_picmip;
3272 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3273 {
3274         int j;
3275         unsigned char *pixels;
3276         unsigned char *bumppixels;
3277         unsigned char *basepixels = NULL;
3278         int basepixels_width = 0;
3279         int basepixels_height = 0;
3280         skinframe_t *skinframe;
3281         rtexture_t *ddsbase = NULL;
3282         qboolean ddshasalpha = false;
3283         float ddsavgcolor[4];
3284         char basename[MAX_QPATH];
3285         int miplevel = R_PicmipForFlags(textureflags);
3286         int savemiplevel = miplevel;
3287         int mymiplevel;
3288         char vabuf[1024];
3289
3290         if (cls.state == ca_dedicated)
3291                 return NULL;
3292
3293         // return an existing skinframe if already loaded
3294         // if loading of the first image fails, don't make a new skinframe as it
3295         // would cause all future lookups of this to be missing
3296         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3297         if (skinframe && skinframe->base)
3298                 return skinframe;
3299
3300         Image_StripImageExtension(name, basename, sizeof(basename));
3301
3302         // check for DDS texture file first
3303         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3304         {
3305                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3306                 if (basepixels == NULL)
3307                         return NULL;
3308         }
3309
3310         // FIXME handle miplevel
3311
3312         if (developer_loading.integer)
3313                 Con_Printf("loading skin \"%s\"\n", name);
3314
3315         // we've got some pixels to store, so really allocate this new texture now
3316         if (!skinframe)
3317                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3318         textureflags &= ~TEXF_FORCE_RELOAD;
3319         skinframe->stain = NULL;
3320         skinframe->merged = NULL;
3321         skinframe->base = NULL;
3322         skinframe->pants = NULL;
3323         skinframe->shirt = NULL;
3324         skinframe->nmap = NULL;
3325         skinframe->gloss = NULL;
3326         skinframe->glow = NULL;
3327         skinframe->fog = NULL;
3328         skinframe->reflect = NULL;
3329         skinframe->hasalpha = false;
3330
3331         if (ddsbase)
3332         {
3333                 skinframe->base = ddsbase;
3334                 skinframe->hasalpha = ddshasalpha;
3335                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3336                 if (r_loadfog && skinframe->hasalpha)
3337                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3338                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3339         }
3340         else
3341         {
3342                 basepixels_width = image_width;
3343                 basepixels_height = image_height;
3344                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3345                 if (textureflags & TEXF_ALPHA)
3346                 {
3347                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3348                         {
3349                                 if (basepixels[j] < 255)
3350                                 {
3351                                         skinframe->hasalpha = true;
3352                                         break;
3353                                 }
3354                         }
3355                         if (r_loadfog && skinframe->hasalpha)
3356                         {
3357                                 // has transparent pixels
3358                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3359                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3360                                 {
3361                                         pixels[j+0] = 255;
3362                                         pixels[j+1] = 255;
3363                                         pixels[j+2] = 255;
3364                                         pixels[j+3] = basepixels[j+3];
3365                                 }
3366                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3367                                 Mem_Free(pixels);
3368                         }
3369                 }
3370                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3371 #ifndef USE_GLES2
3372                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3373                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3374                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3375                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3376                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3377 #endif
3378         }
3379
3380         if (r_loaddds)
3381         {
3382                 mymiplevel = savemiplevel;
3383                 if (r_loadnormalmap)
3384                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3385                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3386                 if (r_loadgloss)
3387                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3388                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3389                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3390                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3391         }
3392
3393         // _norm is the name used by tenebrae and has been adopted as standard
3394         if (r_loadnormalmap && skinframe->nmap == NULL)
3395         {
3396                 mymiplevel = savemiplevel;
3397                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3398                 {
3399                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3400                         Mem_Free(pixels);
3401                         pixels = NULL;
3402                 }
3403                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3404                 {
3405                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3406                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3407                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3408                         Mem_Free(pixels);
3409                         Mem_Free(bumppixels);
3410                 }
3411                 else if (r_shadow_bumpscale_basetexture.value > 0)
3412                 {
3413                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3414                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3415                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3416                         Mem_Free(pixels);
3417                 }
3418 #ifndef USE_GLES2
3419                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3420                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3421 #endif
3422         }
3423
3424         // _luma is supported only for tenebrae compatibility
3425         // _glow is the preferred name
3426         mymiplevel = savemiplevel;
3427         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3428         {
3429                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3430 #ifndef USE_GLES2
3431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3432                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3433 #endif
3434                 Mem_Free(pixels);pixels = NULL;
3435         }
3436
3437         mymiplevel = savemiplevel;
3438         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3439         {
3440                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3441 #ifndef USE_GLES2
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3443                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3444 #endif
3445                 Mem_Free(pixels);
3446                 pixels = NULL;
3447         }
3448
3449         mymiplevel = savemiplevel;
3450         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3451         {
3452                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3453 #ifndef USE_GLES2
3454                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3455                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3456 #endif
3457                 Mem_Free(pixels);
3458                 pixels = NULL;
3459         }
3460
3461         mymiplevel = savemiplevel;
3462         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3463         {
3464                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3465 #ifndef USE_GLES2
3466                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3467                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3468 #endif
3469                 Mem_Free(pixels);
3470                 pixels = NULL;
3471         }
3472
3473         mymiplevel = savemiplevel;
3474         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3475         {
3476                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3477 #ifndef USE_GLES2
3478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3479                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3480 #endif
3481                 Mem_Free(pixels);
3482                 pixels = NULL;
3483         }
3484
3485         if (basepixels)
3486                 Mem_Free(basepixels);
3487
3488         return skinframe;
3489 }
3490
3491 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3492 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3493 {
3494         int i;
3495         unsigned char *temp1, *temp2;
3496         skinframe_t *skinframe;
3497         char vabuf[1024];
3498
3499         if (cls.state == ca_dedicated)
3500                 return NULL;
3501
3502         // if already loaded just return it, otherwise make a new skinframe
3503         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3504         if (skinframe && skinframe->base)
3505                 return skinframe;
3506         textureflags &= ~TEXF_FORCE_RELOAD;
3507
3508         skinframe->stain = NULL;
3509         skinframe->merged = NULL;
3510         skinframe->base = NULL;
3511         skinframe->pants = NULL;
3512         skinframe->shirt = NULL;
3513         skinframe->nmap = NULL;
3514         skinframe->gloss = NULL;
3515         skinframe->glow = NULL;
3516         skinframe->fog = NULL;
3517         skinframe->reflect = NULL;
3518         skinframe->hasalpha = false;
3519
3520         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3521         if (!skindata)
3522                 return NULL;
3523
3524         if (developer_loading.integer)
3525                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3526
3527         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3528         {
3529                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3530                 temp2 = temp1 + width * height * 4;
3531                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3532                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3533                 Mem_Free(temp1);
3534         }
3535         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3536         if (textureflags & TEXF_ALPHA)
3537         {
3538                 for (i = 3;i < width * height * 4;i += 4)
3539                 {
3540                         if (skindata[i] < 255)
3541                         {
3542                                 skinframe->hasalpha = true;
3543                                 break;
3544                         }
3545                 }
3546                 if (r_loadfog && skinframe->hasalpha)
3547                 {
3548                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3549                         memcpy(fogpixels, skindata, width * height * 4);
3550                         for (i = 0;i < width * height * 4;i += 4)
3551                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3552                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3553                         Mem_Free(fogpixels);
3554                 }
3555         }
3556
3557         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3558         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3559
3560         return skinframe;
3561 }
3562
3563 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3564 {
3565         int i;
3566         int featuresmask;
3567         skinframe_t *skinframe;
3568
3569         if (cls.state == ca_dedicated)
3570                 return NULL;
3571
3572         // if already loaded just return it, otherwise make a new skinframe
3573         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3574         if (skinframe && skinframe->base)
3575                 return skinframe;
3576         textureflags &= ~TEXF_FORCE_RELOAD;
3577
3578         skinframe->stain = NULL;
3579         skinframe->merged = NULL;
3580         skinframe->base = NULL;
3581         skinframe->pants = NULL;
3582         skinframe->shirt = NULL;
3583         skinframe->nmap = NULL;
3584         skinframe->gloss = NULL;
3585         skinframe->glow = NULL;
3586         skinframe->fog = NULL;
3587         skinframe->reflect = NULL;
3588         skinframe->hasalpha = false;
3589
3590         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3591         if (!skindata)
3592                 return NULL;
3593
3594         if (developer_loading.integer)
3595                 Con_Printf("loading quake skin \"%s\"\n", name);
3596
3597         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3598         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3599         memcpy(skinframe->qpixels, skindata, width*height);
3600         skinframe->qwidth = width;
3601         skinframe->qheight = height;
3602
3603         featuresmask = 0;
3604         for (i = 0;i < width * height;i++)
3605                 featuresmask |= palette_featureflags[skindata[i]];
3606
3607         skinframe->hasalpha = false;
3608         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3609         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3610         skinframe->qgeneratemerged = true;
3611         skinframe->qgeneratebase = skinframe->qhascolormapping;
3612         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3613
3614         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3615         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3616
3617         return skinframe;
3618 }
3619
3620 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3621 {
3622         int width;
3623         int height;
3624         unsigned char *skindata;
3625         char vabuf[1024];
3626
3627         if (!skinframe->qpixels)
3628                 return;
3629
3630         if (!skinframe->qhascolormapping)
3631                 colormapped = false;
3632
3633         if (colormapped)
3634         {
3635                 if (!skinframe->qgeneratebase)
3636                         return;
3637         }
3638         else
3639         {
3640                 if (!skinframe->qgeneratemerged)
3641                         return;
3642         }
3643
3644         width = skinframe->qwidth;
3645         height = skinframe->qheight;
3646         skindata = skinframe->qpixels;
3647
3648         if (skinframe->qgeneratenmap)
3649         {
3650                 unsigned char *temp1, *temp2;
3651                 skinframe->qgeneratenmap = false;
3652                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3653                 temp2 = temp1 + width * height * 4;
3654                 // use either a custom palette or the quake palette
3655                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3656                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3657                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3658                 Mem_Free(temp1);
3659         }
3660
3661         if (skinframe->qgenerateglow)
3662         {
3663                 skinframe->qgenerateglow = false;
3664                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3665         }
3666
3667         if (colormapped)
3668         {
3669                 skinframe->qgeneratebase = false;
3670                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3671                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3672                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3673         }
3674         else
3675         {
3676                 skinframe->qgeneratemerged = false;
3677                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3678         }
3679
3680         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3681         {
3682                 Mem_Free(skinframe->qpixels);
3683                 skinframe->qpixels = NULL;
3684         }
3685 }
3686
3687 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3688 {
3689         int i;
3690         skinframe_t *skinframe;
3691         char vabuf[1024];
3692
3693         if (cls.state == ca_dedicated)
3694                 return NULL;
3695
3696         // if already loaded just return it, otherwise make a new skinframe
3697         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3698         if (skinframe && skinframe->base)
3699                 return skinframe;
3700         textureflags &= ~TEXF_FORCE_RELOAD;
3701
3702         skinframe->stain = NULL;
3703         skinframe->merged = NULL;
3704         skinframe->base = NULL;
3705         skinframe->pants = NULL;
3706         skinframe->shirt = NULL;
3707         skinframe->nmap = NULL;
3708         skinframe->gloss = NULL;
3709         skinframe->glow = NULL;
3710         skinframe->fog = NULL;
3711         skinframe->reflect = NULL;
3712         skinframe->hasalpha = false;
3713
3714         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3715         if (!skindata)
3716                 return NULL;
3717
3718         if (developer_loading.integer)
3719                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3720
3721         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3722         if (textureflags & TEXF_ALPHA)
3723         {
3724                 for (i = 0;i < width * height;i++)
3725                 {
3726                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3727                         {
3728                                 skinframe->hasalpha = true;
3729                                 break;
3730                         }
3731                 }
3732                 if (r_loadfog && skinframe->hasalpha)
3733                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3734         }
3735
3736         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3737         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3738
3739         return skinframe;
3740 }
3741
3742 skinframe_t *R_SkinFrame_LoadMissing(void)
3743 {
3744         skinframe_t *skinframe;
3745
3746         if (cls.state == ca_dedicated)
3747                 return NULL;
3748
3749         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3750         skinframe->stain = NULL;
3751         skinframe->merged = NULL;
3752         skinframe->base = NULL;
3753         skinframe->pants = NULL;
3754         skinframe->shirt = NULL;
3755         skinframe->nmap = NULL;
3756         skinframe->gloss = NULL;
3757         skinframe->glow = NULL;
3758         skinframe->fog = NULL;
3759         skinframe->reflect = NULL;
3760         skinframe->hasalpha = false;
3761
3762         skinframe->avgcolor[0] = rand() / RAND_MAX;
3763         skinframe->avgcolor[1] = rand() / RAND_MAX;
3764         skinframe->avgcolor[2] = rand() / RAND_MAX;
3765         skinframe->avgcolor[3] = 1;
3766
3767         return skinframe;
3768 }
3769
3770 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3771 typedef struct suffixinfo_s
3772 {
3773         const char *suffix;
3774         qboolean flipx, flipy, flipdiagonal;
3775 }
3776 suffixinfo_t;
3777 static suffixinfo_t suffix[3][6] =
3778 {
3779         {
3780                 {"px",   false, false, false},
3781                 {"nx",   false, false, false},
3782                 {"py",   false, false, false},
3783                 {"ny",   false, false, false},
3784                 {"pz",   false, false, false},
3785                 {"nz",   false, false, false}
3786         },
3787         {
3788                 {"posx", false, false, false},
3789                 {"negx", false, false, false},
3790                 {"posy", false, false, false},
3791                 {"negy", false, false, false},
3792                 {"posz", false, false, false},
3793                 {"negz", false, false, false}
3794         },
3795         {
3796                 {"rt",    true, false,  true},
3797                 {"lf",   false,  true,  true},
3798                 {"ft",    true,  true, false},
3799                 {"bk",   false, false, false},
3800                 {"up",    true, false,  true},
3801                 {"dn",    true, false,  true}
3802         }
3803 };
3804
3805 static int componentorder[4] = {0, 1, 2, 3};
3806
3807 static rtexture_t *R_LoadCubemap(const char *basename)
3808 {
3809         int i, j, cubemapsize;
3810         unsigned char *cubemappixels, *image_buffer;
3811         rtexture_t *cubemaptexture;
3812         char name[256];
3813         // must start 0 so the first loadimagepixels has no requested width/height
3814         cubemapsize = 0;
3815         cubemappixels = NULL;
3816         cubemaptexture = NULL;
3817         // keep trying different suffix groups (posx, px, rt) until one loads
3818         for (j = 0;j < 3 && !cubemappixels;j++)
3819         {
3820                 // load the 6 images in the suffix group
3821                 for (i = 0;i < 6;i++)
3822                 {
3823                         // generate an image name based on the base and and suffix
3824                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3825                         // load it
3826                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3827                         {
3828                                 // an image loaded, make sure width and height are equal
3829                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3830                                 {
3831                                         // if this is the first image to load successfully, allocate the cubemap memory
3832                                         if (!cubemappixels && image_width >= 1)
3833                                         {
3834                                                 cubemapsize = image_width;
3835                                                 // note this clears to black, so unavailable sides are black
3836                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3837                                         }
3838                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3839                                         if (cubemappixels)
3840                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3841                                 }
3842                                 else
3843                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3844                                 // free the image
3845                                 Mem_Free(image_buffer);
3846                         }
3847                 }
3848         }
3849         // if a cubemap loaded, upload it
3850         if (cubemappixels)
3851         {
3852                 if (developer_loading.integer)
3853                         Con_Printf("loading cubemap \"%s\"\n", basename);
3854
3855                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3856                 Mem_Free(cubemappixels);
3857         }
3858         else
3859         {
3860                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3861                 if (developer_loading.integer)
3862                 {
3863                         Con_Printf("(tried tried images ");
3864                         for (j = 0;j < 3;j++)
3865                                 for (i = 0;i < 6;i++)
3866                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3867                         Con_Print(" and was unable to find any of them).\n");
3868                 }
3869         }
3870         return cubemaptexture;
3871 }
3872
3873 rtexture_t *R_GetCubemap(const char *basename)
3874 {
3875         int i;
3876         for (i = 0;i < r_texture_numcubemaps;i++)
3877                 if (r_texture_cubemaps[i] != NULL)
3878                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3879                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3880         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3881                 return r_texture_whitecube;
3882         r_texture_numcubemaps++;
3883         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3884         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3885         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3886         return r_texture_cubemaps[i]->texture;
3887 }
3888
3889 static void R_Main_FreeViewCache(void)
3890 {
3891         if (r_refdef.viewcache.entityvisible)
3892                 Mem_Free(r_refdef.viewcache.entityvisible);
3893         if (r_refdef.viewcache.world_pvsbits)
3894                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3895         if (r_refdef.viewcache.world_leafvisible)
3896                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3897         if (r_refdef.viewcache.world_surfacevisible)
3898                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3899         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3900 }
3901
3902 static void R_Main_ResizeViewCache(void)
3903 {
3904         int numentities = r_refdef.scene.numentities;
3905         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3906         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3907         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3908         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3909         if (r_refdef.viewcache.maxentities < numentities)
3910         {
3911                 r_refdef.viewcache.maxentities = numentities;
3912                 if (r_refdef.viewcache.entityvisible)
3913                         Mem_Free(r_refdef.viewcache.entityvisible);
3914                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3915         }
3916         if (r_refdef.viewcache.world_numclusters != numclusters)
3917         {
3918                 r_refdef.viewcache.world_numclusters = numclusters;
3919                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3920                 if (r_refdef.viewcache.world_pvsbits)
3921                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3922                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3923         }
3924         if (r_refdef.viewcache.world_numleafs != numleafs)
3925         {
3926                 r_refdef.viewcache.world_numleafs = numleafs;
3927                 if (r_refdef.viewcache.world_leafvisible)
3928                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3929                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3930         }
3931         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3932         {
3933                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3934                 if (r_refdef.viewcache.world_surfacevisible)
3935                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3936                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3937         }
3938 }
3939
3940 extern rtexture_t *loadingscreentexture;
3941 static void gl_main_start(void)
3942 {
3943         loadingscreentexture = NULL;
3944         r_texture_blanknormalmap = NULL;
3945         r_texture_white = NULL;
3946         r_texture_grey128 = NULL;
3947         r_texture_black = NULL;
3948         r_texture_whitecube = NULL;
3949         r_texture_normalizationcube = NULL;
3950         r_texture_fogattenuation = NULL;
3951         r_texture_fogheighttexture = NULL;
3952         r_texture_gammaramps = NULL;
3953         r_texture_numcubemaps = 0;
3954
3955         r_loaddds = r_texture_dds_load.integer != 0;
3956         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3957
3958         switch(vid.renderpath)
3959         {
3960         case RENDERPATH_GL20:
3961         case RENDERPATH_D3D9:
3962         case RENDERPATH_D3D10:
3963         case RENDERPATH_D3D11:
3964         case RENDERPATH_SOFT:
3965         case RENDERPATH_GLES2:
3966                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3967                 Cvar_SetValueQuick(&gl_combine, 1);
3968                 Cvar_SetValueQuick(&r_glsl, 1);
3969                 r_loadnormalmap = true;
3970                 r_loadgloss = true;
3971                 r_loadfog = false;
3972                 break;
3973         case RENDERPATH_GL13:
3974         case RENDERPATH_GLES1:
3975                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3976                 Cvar_SetValueQuick(&gl_combine, 1);
3977                 Cvar_SetValueQuick(&r_glsl, 0);
3978                 r_loadnormalmap = false;
3979                 r_loadgloss = false;
3980                 r_loadfog = true;
3981                 break;
3982         case RENDERPATH_GL11:
3983                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3984                 Cvar_SetValueQuick(&gl_combine, 0);
3985                 Cvar_SetValueQuick(&r_glsl, 0);
3986                 r_loadnormalmap = false;
3987                 r_loadgloss = false;
3988                 r_loadfog = true;
3989                 break;
3990         }
3991
3992         R_AnimCache_Free();
3993         R_FrameData_Reset();
3994
3995         r_numqueries = 0;
3996         r_maxqueries = 0;
3997         memset(r_queries, 0, sizeof(r_queries));
3998
3999         r_qwskincache = NULL;
4000         r_qwskincache_size = 0;
4001
4002         // due to caching of texture_t references, the collision cache must be reset
4003         Collision_Cache_Reset(true);
4004
4005         // set up r_skinframe loading system for textures
4006         memset(&r_skinframe, 0, sizeof(r_skinframe));
4007         r_skinframe.loadsequence = 1;
4008         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4009
4010         r_main_texturepool = R_AllocTexturePool();
4011         R_BuildBlankTextures();
4012         R_BuildNoTexture();
4013         if (vid.support.arb_texture_cube_map)
4014         {
4015                 R_BuildWhiteCube();
4016                 R_BuildNormalizationCube();
4017         }
4018         r_texture_fogattenuation = NULL;
4019         r_texture_fogheighttexture = NULL;
4020         r_texture_gammaramps = NULL;
4021         //r_texture_fogintensity = NULL;
4022         memset(&r_fb, 0, sizeof(r_fb));
4023         r_glsl_permutation = NULL;
4024         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4025         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4026         glslshaderstring = NULL;
4027 #ifdef SUPPORTD3D
4028         r_hlsl_permutation = NULL;
4029         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4030         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4031 #endif
4032         hlslshaderstring = NULL;
4033         memset(&r_svbsp, 0, sizeof (r_svbsp));
4034
4035         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4036         r_texture_numcubemaps = 0;
4037
4038         r_refdef.fogmasktable_density = 0;
4039 }
4040
4041 static void gl_main_shutdown(void)
4042 {
4043         R_AnimCache_Free();
4044         R_FrameData_Reset();
4045
4046         R_Main_FreeViewCache();
4047
4048         switch(vid.renderpath)
4049         {
4050         case RENDERPATH_GL11:
4051         case RENDERPATH_GL13:
4052         case RENDERPATH_GL20:
4053         case RENDERPATH_GLES1:
4054         case RENDERPATH_GLES2:
4055 #ifdef GL_SAMPLES_PASSED_ARB
4056                 if (r_maxqueries)
4057                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4058 #endif
4059                 break;
4060         case RENDERPATH_D3D9:
4061                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4062                 break;
4063         case RENDERPATH_D3D10:
4064                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4065                 break;
4066         case RENDERPATH_D3D11:
4067                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4068                 break;
4069         case RENDERPATH_SOFT:
4070                 break;
4071         }
4072
4073         r_numqueries = 0;
4074         r_maxqueries = 0;
4075         memset(r_queries, 0, sizeof(r_queries));
4076
4077         r_qwskincache = NULL;
4078         r_qwskincache_size = 0;
4079
4080         // clear out the r_skinframe state
4081         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4082         memset(&r_skinframe, 0, sizeof(r_skinframe));
4083
4084         if (r_svbsp.nodes)
4085                 Mem_Free(r_svbsp.nodes);
4086         memset(&r_svbsp, 0, sizeof (r_svbsp));
4087         R_FreeTexturePool(&r_main_texturepool);
4088         loadingscreentexture = NULL;
4089         r_texture_blanknormalmap = NULL;
4090         r_texture_white = NULL;
4091         r_texture_grey128 = NULL;
4092         r_texture_black = NULL;
4093         r_texture_whitecube = NULL;
4094         r_texture_normalizationcube = NULL;
4095         r_texture_fogattenuation = NULL;
4096         r_texture_fogheighttexture = NULL;
4097         r_texture_gammaramps = NULL;
4098         r_texture_numcubemaps = 0;
4099         //r_texture_fogintensity = NULL;
4100         memset(&r_fb, 0, sizeof(r_fb));
4101         R_GLSL_Restart_f();
4102
4103         r_glsl_permutation = NULL;
4104         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4105         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4106         glslshaderstring = NULL;
4107 #ifdef SUPPORTD3D
4108         r_hlsl_permutation = NULL;
4109         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4110         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4111 #endif
4112         hlslshaderstring = NULL;
4113 }
4114
4115 static void gl_main_newmap(void)
4116 {
4117         // FIXME: move this code to client
4118         char *entities, entname[MAX_QPATH];
4119         if (r_qwskincache)
4120                 Mem_Free(r_qwskincache);
4121         r_qwskincache = NULL;
4122         r_qwskincache_size = 0;
4123         if (cl.worldmodel)
4124         {
4125                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4126                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4127                 {
4128                         CL_ParseEntityLump(entities);
4129                         Mem_Free(entities);
4130                         return;
4131                 }
4132                 if (cl.worldmodel->brush.entities)
4133                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4134         }
4135         R_Main_FreeViewCache();
4136
4137         R_FrameData_Reset();
4138 }
4139
4140 void GL_Main_Init(void)
4141 {
4142         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4143
4144         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4145         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4146         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4147         if (gamemode == GAME_NEHAHRA)
4148         {
4149                 Cvar_RegisterVariable (&gl_fogenable);
4150                 Cvar_RegisterVariable (&gl_fogdensity);
4151                 Cvar_RegisterVariable (&gl_fogred);
4152                 Cvar_RegisterVariable (&gl_foggreen);
4153                 Cvar_RegisterVariable (&gl_fogblue);
4154                 Cvar_RegisterVariable (&gl_fogstart);
4155                 Cvar_RegisterVariable (&gl_fogend);
4156                 Cvar_RegisterVariable (&gl_skyclip);
4157         }
4158         Cvar_RegisterVariable(&r_motionblur);
4159         Cvar_RegisterVariable(&r_damageblur);
4160         Cvar_RegisterVariable(&r_motionblur_averaging);
4161         Cvar_RegisterVariable(&r_motionblur_randomize);
4162         Cvar_RegisterVariable(&r_motionblur_minblur);
4163         Cvar_RegisterVariable(&r_motionblur_maxblur);
4164         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4165         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4166         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4167         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4168         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4169         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4170         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4171         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4172         Cvar_RegisterVariable(&r_equalize_entities_by);
4173         Cvar_RegisterVariable(&r_equalize_entities_to);
4174         Cvar_RegisterVariable(&r_depthfirst);
4175         Cvar_RegisterVariable(&r_useinfinitefarclip);
4176         Cvar_RegisterVariable(&r_farclip_base);
4177         Cvar_RegisterVariable(&r_farclip_world);
4178         Cvar_RegisterVariable(&r_nearclip);
4179         Cvar_RegisterVariable(&r_deformvertexes);
4180         Cvar_RegisterVariable(&r_transparent);
4181         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4182         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4183         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4184         Cvar_RegisterVariable(&r_showoverdraw);
4185         Cvar_RegisterVariable(&r_showbboxes);
4186         Cvar_RegisterVariable(&r_showsurfaces);
4187         Cvar_RegisterVariable(&r_showtris);
4188         Cvar_RegisterVariable(&r_shownormals);
4189         Cvar_RegisterVariable(&r_showlighting);
4190         Cvar_RegisterVariable(&r_showshadowvolumes);
4191         Cvar_RegisterVariable(&r_showcollisionbrushes);
4192         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4193         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4194         Cvar_RegisterVariable(&r_showdisabledepthtest);
4195         Cvar_RegisterVariable(&r_drawportals);
4196         Cvar_RegisterVariable(&r_drawentities);
4197         Cvar_RegisterVariable(&r_draw2d);
4198         Cvar_RegisterVariable(&r_drawworld);
4199         Cvar_RegisterVariable(&r_cullentities_trace);
4200         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4201         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4202         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4203         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4204         Cvar_RegisterVariable(&r_sortentities);
4205         Cvar_RegisterVariable(&r_drawviewmodel);
4206         Cvar_RegisterVariable(&r_drawexteriormodel);
4207         Cvar_RegisterVariable(&r_speeds);
4208         Cvar_RegisterVariable(&r_fullbrights);
4209         Cvar_RegisterVariable(&r_wateralpha);
4210         Cvar_RegisterVariable(&r_dynamic);
4211         Cvar_RegisterVariable(&r_fakelight);
4212         Cvar_RegisterVariable(&r_fakelight_intensity);
4213         Cvar_RegisterVariable(&r_fullbright);
4214         Cvar_RegisterVariable(&r_shadows);
4215         Cvar_RegisterVariable(&r_shadows_darken);
4216         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4217         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4218         Cvar_RegisterVariable(&r_shadows_throwdistance);
4219         Cvar_RegisterVariable(&r_shadows_throwdirection);
4220         Cvar_RegisterVariable(&r_shadows_focus);
4221         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4222         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4223         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4224         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4225         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4226         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4227         Cvar_RegisterVariable(&r_fog_exp2);
4228         Cvar_RegisterVariable(&r_fog_clear);
4229         Cvar_RegisterVariable(&r_drawfog);
4230         Cvar_RegisterVariable(&r_transparentdepthmasking);
4231         Cvar_RegisterVariable(&r_transparent_sortmindist);
4232         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4233         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4234         Cvar_RegisterVariable(&r_texture_dds_load);
4235         Cvar_RegisterVariable(&r_texture_dds_save);
4236         Cvar_RegisterVariable(&r_textureunits);
4237         Cvar_RegisterVariable(&gl_combine);
4238         Cvar_RegisterVariable(&r_usedepthtextures);
4239         Cvar_RegisterVariable(&r_viewfbo);
4240         Cvar_RegisterVariable(&r_viewscale);
4241         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4242         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4243         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4244         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4245         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4246         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4247         Cvar_RegisterVariable(&r_glsl);
4248         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4249         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4250         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4251         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4252         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4253         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4254         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4255         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4256         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4257         Cvar_RegisterVariable(&r_glsl_postprocess);
4258         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4259         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4260         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4262         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4266
4267         Cvar_RegisterVariable(&r_water);
4268         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4269         Cvar_RegisterVariable(&r_water_clippingplanebias);
4270         Cvar_RegisterVariable(&r_water_refractdistort);
4271         Cvar_RegisterVariable(&r_water_reflectdistort);
4272         Cvar_RegisterVariable(&r_water_scissormode);
4273         Cvar_RegisterVariable(&r_water_lowquality);
4274         Cvar_RegisterVariable(&r_water_hideplayer);
4275         Cvar_RegisterVariable(&r_water_fbo);
4276
4277         Cvar_RegisterVariable(&r_lerpsprites);
4278         Cvar_RegisterVariable(&r_lerpmodels);
4279         Cvar_RegisterVariable(&r_lerplightstyles);
4280         Cvar_RegisterVariable(&r_waterscroll);
4281         Cvar_RegisterVariable(&r_bloom);
4282         Cvar_RegisterVariable(&r_bloom_colorscale);
4283         Cvar_RegisterVariable(&r_bloom_brighten);
4284         Cvar_RegisterVariable(&r_bloom_blur);
4285         Cvar_RegisterVariable(&r_bloom_resolution);
4286         Cvar_RegisterVariable(&r_bloom_colorexponent);
4287         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4288         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4289         Cvar_RegisterVariable(&r_hdr_glowintensity);
4290         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4294         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4295         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4296         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4298         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4299         Cvar_RegisterVariable(&developer_texturelogging);
4300         Cvar_RegisterVariable(&gl_lightmaps);
4301         Cvar_RegisterVariable(&r_test);
4302         Cvar_RegisterVariable(&r_glsl_saturation);
4303         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4304         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4305         Cvar_RegisterVariable(&r_framedatasize);
4306         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4307                 Cvar_SetValue("r_fullbrights", 0);
4308         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4309 }
4310
4311 void Render_Init(void)
4312 {
4313         gl_backend_init();
4314         R_Textures_Init();
4315         GL_Main_Init();
4316         Font_Init();
4317         GL_Draw_Init();
4318         R_Shadow_Init();
4319         R_Sky_Init();
4320         GL_Surf_Init();
4321         Sbar_Init();
4322         R_Particles_Init();
4323         R_Explosion_Init();
4324         R_LightningBeams_Init();
4325         Mod_RenderInit();
4326 }
4327
4328 /*
4329 ===============
4330 GL_Init
4331 ===============
4332 */
4333 #ifndef USE_GLES2
4334 extern char *ENGINE_EXTENSIONS;
4335 void GL_Init (void)
4336 {
4337         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4338         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4339         gl_version = (const char *)qglGetString(GL_VERSION);
4340         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4341
4342         if (!gl_extensions)
4343                 gl_extensions = "";
4344         if (!gl_platformextensions)
4345                 gl_platformextensions = "";
4346
4347         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4348         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4349         Con_Printf("GL_VERSION: %s\n", gl_version);
4350         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4351         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4352
4353         VID_CheckExtensions();
4354
4355         // LordHavoc: report supported extensions
4356         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4357
4358         // clear to black (loading plaque will be seen over this)
4359         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4360 }
4361 #endif
4362
4363 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4364 {
4365         int i;
4366         mplane_t *p;
4367         if (r_trippy.integer)
4368                 return false;
4369         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4370         {
4371                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4372                 if (i == 4)
4373                         continue;
4374                 p = r_refdef.view.frustum + i;
4375                 switch(p->signbits)
4376                 {
4377                 default:
4378                 case 0:
4379                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 1:
4383                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 2:
4387                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 3:
4391                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 4:
4395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 5:
4399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 6:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 7:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 }
4411         }
4412         return false;
4413 }
4414
4415 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4416 {
4417         int i;
4418         const mplane_t *p;
4419         if (r_trippy.integer)
4420                 return false;
4421         for (i = 0;i < numplanes;i++)
4422         {
4423                 p = planes + i;
4424                 switch(p->signbits)
4425                 {
4426                 default:
4427                 case 0:
4428                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 1:
4432                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 2:
4436                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 3:
4440                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 4:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 5:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 6:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 7:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 }
4460         }
4461         return false;
4462 }
4463
4464 //==================================================================================
4465
4466 // LordHavoc: this stores temporary data used within the same frame
4467
4468 typedef struct r_framedata_mem_s
4469 {
4470         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4471         size_t size; // how much usable space
4472         size_t current; // how much space in use
4473         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4474         size_t wantedsize; // how much space was allocated
4475         unsigned char *data; // start of real data (16byte aligned)
4476 }
4477 r_framedata_mem_t;
4478
4479 static r_framedata_mem_t *r_framedata_mem;
4480
4481 void R_FrameData_Reset(void)
4482 {
4483         while (r_framedata_mem)
4484         {
4485                 r_framedata_mem_t *next = r_framedata_mem->purge;
4486                 Mem_Free(r_framedata_mem);
4487                 r_framedata_mem = next;
4488         }
4489 }
4490
4491 static void R_FrameData_Resize(void)
4492 {
4493         size_t wantedsize;
4494         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4495         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4496         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4497         {
4498                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4499                 newmem->wantedsize = wantedsize;
4500                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4501                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4502                 newmem->current = 0;
4503                 newmem->mark = 0;
4504                 newmem->purge = r_framedata_mem;
4505                 r_framedata_mem = newmem;
4506         }
4507 }
4508
4509 void R_FrameData_NewFrame(void)
4510 {
4511         R_FrameData_Resize();
4512         if (!r_framedata_mem)
4513                 return;
4514         // if we ran out of space on the last frame, free the old memory now
4515         while (r_framedata_mem->purge)
4516         {
4517                 // repeatedly remove the second item in the list, leaving only head
4518                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4519                 Mem_Free(r_framedata_mem->purge);
4520                 r_framedata_mem->purge = next;
4521         }
4522         // reset the current mem pointer
4523         r_framedata_mem->current = 0;
4524         r_framedata_mem->mark = 0;
4525 }
4526
4527 void *R_FrameData_Alloc(size_t size)
4528 {
4529         void *data;
4530
4531         // align to 16 byte boundary - the data pointer is already aligned, so we
4532         // only need to ensure the size of every allocation is also aligned
4533         size = (size + 15) & ~15;
4534
4535         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4536         {
4537                 // emergency - we ran out of space, allocate more memory
4538                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4539                 R_FrameData_Resize();
4540         }
4541
4542         data = r_framedata_mem->data + r_framedata_mem->current;
4543         r_framedata_mem->current += size;
4544
4545         // count the usage for stats
4546         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4547         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4548
4549         return (void *)data;
4550 }
4551
4552 void *R_FrameData_Store(size_t size, void *data)
4553 {
4554         void *d = R_FrameData_Alloc(size);
4555         if (d && data)
4556                 memcpy(d, data, size);
4557         return d;
4558 }
4559
4560 void R_FrameData_SetMark(void)
4561 {
4562         if (!r_framedata_mem)
4563                 return;
4564         r_framedata_mem->mark = r_framedata_mem->current;
4565 }
4566
4567 void R_FrameData_ReturnToMark(void)
4568 {
4569         if (!r_framedata_mem)
4570                 return;
4571         r_framedata_mem->current = r_framedata_mem->mark;
4572 }
4573
4574 //==================================================================================
4575
4576 // LordHavoc: animcache originally written by Echon, rewritten since then
4577
4578 /**
4579  * Animation cache prevents re-generating mesh data for an animated model
4580  * multiple times in one frame for lighting, shadowing, reflections, etc.
4581  */
4582
4583 void R_AnimCache_Free(void)
4584 {
4585 }
4586
4587 void R_AnimCache_ClearCache(void)
4588 {
4589         int i;
4590         entity_render_t *ent;
4591
4592         for (i = 0;i < r_refdef.scene.numentities;i++)
4593         {
4594                 ent = r_refdef.scene.entities[i];
4595                 ent->animcache_vertex3f = NULL;
4596                 ent->animcache_normal3f = NULL;
4597                 ent->animcache_svector3f = NULL;
4598                 ent->animcache_tvector3f = NULL;
4599                 ent->animcache_vertexmesh = NULL;
4600                 ent->animcache_vertex3fbuffer = NULL;
4601                 ent->animcache_vertexmeshbuffer = NULL;
4602         }
4603 }
4604
4605 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4606 {
4607         int i;
4608
4609         // check if we need the meshbuffers
4610         if (!vid.useinterleavedarrays)
4611                 return;
4612
4613         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4614                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4615         // TODO: upload vertex3f buffer?
4616         if (ent->animcache_vertexmesh)
4617         {
4618                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4619                 for (i = 0;i < numvertices;i++)
4620                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4621                 if (ent->animcache_svector3f)
4622                         for (i = 0;i < numvertices;i++)
4623                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4624                 if (ent->animcache_tvector3f)
4625                         for (i = 0;i < numvertices;i++)
4626                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4627                 if (ent->animcache_normal3f)
4628                         for (i = 0;i < numvertices;i++)
4629                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4630                 // TODO: upload vertexmeshbuffer?
4631         }
4632 }
4633
4634 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4635 {
4636         dp_model_t *model = ent->model;
4637         int numvertices;
4638         // see if it's already cached this frame
4639         if (ent->animcache_vertex3f)
4640         {
4641                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4642                 if (wantnormals || wanttangents)
4643                 {
4644                         if (ent->animcache_normal3f)
4645                                 wantnormals = false;
4646                         if (ent->animcache_svector3f)
4647                                 wanttangents = false;
4648                         if (wantnormals || wanttangents)
4649                         {
4650                                 numvertices = model->surfmesh.num_vertices;
4651                                 if (wantnormals)
4652                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                                 if (wanttangents)
4654                                 {
4655                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4656                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4657                                 }
4658                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4659                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4660                         }
4661                 }
4662         }
4663         else
4664         {
4665                 // see if this ent is worth caching
4666                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4667                         return false;
4668                 // get some memory for this entity and generate mesh data
4669                 numvertices = model->surfmesh.num_vertices;
4670                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671                 if (wantnormals)
4672                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                 if (wanttangents)
4674                 {
4675                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4676                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4677                 }
4678                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4679                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4680         }
4681         return true;
4682 }
4683
4684 void R_AnimCache_CacheVisibleEntities(void)
4685 {
4686         int i;
4687         qboolean wantnormals = true;
4688         qboolean wanttangents = !r_showsurfaces.integer;
4689
4690         switch(vid.renderpath)
4691         {
4692         case RENDERPATH_GL20:
4693         case RENDERPATH_D3D9:
4694         case RENDERPATH_D3D10:
4695         case RENDERPATH_D3D11:
4696         case RENDERPATH_GLES2:
4697                 break;
4698         case RENDERPATH_GL11:
4699         case RENDERPATH_GL13:
4700         case RENDERPATH_GLES1:
4701                 wanttangents = false;
4702                 break;
4703         case RENDERPATH_SOFT:
4704                 break;
4705         }
4706
4707         if (r_shownormals.integer)
4708                 wanttangents = wantnormals = true;
4709
4710         // TODO: thread this
4711         // NOTE: R_PrepareRTLights() also caches entities
4712
4713         for (i = 0;i < r_refdef.scene.numentities;i++)
4714                 if (r_refdef.viewcache.entityvisible[i])
4715                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4716 }
4717
4718 //==================================================================================
4719
4720 extern cvar_t r_overheadsprites_pushback;
4721
4722 static void R_View_UpdateEntityLighting (void)
4723 {
4724         int i;
4725         entity_render_t *ent;
4726         vec3_t tempdiffusenormal, avg;
4727         vec_t f, fa, fd, fdd;
4728         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4729
4730         for (i = 0;i < r_refdef.scene.numentities;i++)
4731         {
4732                 ent = r_refdef.scene.entities[i];
4733
4734                 // skip unseen models
4735                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4736                         continue;
4737
4738                 // skip bsp models
4739                 if (ent->model && ent->model == cl.worldmodel)
4740                 {
4741                         // TODO: use modellight for r_ambient settings on world?
4742                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4743                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4744                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4745                         continue;
4746                 }
4747                 
4748                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4749                 {
4750                         // aleady updated by CSQC
4751                         // TODO: force modellight on BSP models in this case?
4752                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4753                 }
4754                 else
4755                 {
4756                         // fetch the lighting from the worldmodel data
4757                         VectorClear(ent->modellight_ambient);
4758                         VectorClear(ent->modellight_diffuse);
4759                         VectorClear(tempdiffusenormal);
4760                         if (ent->flags & RENDER_LIGHT)
4761                         {
4762                                 vec3_t org;
4763                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4764
4765                                 // complete lightning for lit sprites
4766                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4767                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4768                                 {
4769                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4770                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4771                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4772                                 }
4773                                 else
4774                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4775
4776                                 if(ent->flags & RENDER_EQUALIZE)
4777                                 {
4778                                         // first fix up ambient lighting...
4779                                         if(r_equalize_entities_minambient.value > 0)
4780                                         {
4781                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4782                                                 if(fd > 0)
4783                                                 {
4784                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4785                                                         if(fa < r_equalize_entities_minambient.value * fd)
4786                                                         {
4787                                                                 // solve:
4788                                                                 //   fa'/fd' = minambient
4789                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4790                                                                 //   ...
4791                                                                 //   fa' = fd' * minambient
4792                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4793                                                                 //   ...
4794                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4795                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4796                                                                 //   ...
4797                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4798                                                                 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
4799                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4800                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4801                                                         }
4802                                                 }
4803                                         }
4804
4805                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4806                                         {
4807                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4808                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4809                                                 f = fa + 0.25 * fd;
4810                                                 if(f > 0)
4811                                                 {
4812                                                         // adjust brightness and saturation to target
4813                                                         avg[0] = avg[1] = avg[2] = fa / f;
4814                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4815                                                         avg[0] = avg[1] = avg[2] = fd / f;
4816                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4817                                                 }
4818                                         }
4819                                 }
4820                         }
4821                         else // highly rare
4822                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4823                 }
4824
4825                 // move the light direction into modelspace coordinates for lighting code
4826                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4827                 if(VectorLength2(ent->modellight_lightdir) == 0)
4828                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4829                 VectorNormalize(ent->modellight_lightdir);
4830         }
4831 }
4832
4833 #define MAX_LINEOFSIGHTTRACES 64
4834
4835 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4836 {
4837         int i;
4838         vec3_t boxmins, boxmaxs;
4839         vec3_t start;
4840         vec3_t end;
4841         dp_model_t *model = r_refdef.scene.worldmodel;
4842
4843         if (!model || !model->brush.TraceLineOfSight)
4844                 return true;
4845
4846         // expand the box a little
4847         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4848         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4849         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4850         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4851         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4852         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4853
4854         // return true if eye is inside enlarged box
4855         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4856                 return true;
4857
4858         // try center
4859         VectorCopy(eye, start);
4860         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4861         if (model->brush.TraceLineOfSight(model, start, end))
4862                 return true;
4863
4864         // try various random positions
4865         for (i = 0;i < numsamples;i++)
4866         {
4867                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4868                 if (model->brush.TraceLineOfSight(model, start, end))
4869                         return true;
4870         }
4871
4872         return false;
4873 }
4874
4875
4876 static void R_View_UpdateEntityVisible (void)
4877 {
4878         int i;
4879         int renderimask;
4880         int samples;
4881         entity_render_t *ent;
4882
4883         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4884                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4885                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4886                 :                                                          RENDER_EXTERIORMODEL;
4887         if (!r_drawviewmodel.integer)
4888                 renderimask |= RENDER_VIEWMODEL;
4889         if (!r_drawexteriormodel.integer)
4890                 renderimask |= RENDER_EXTERIORMODEL;
4891         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4892         {
4893                 // worldmodel can check visibility
4894                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4895                 for (i = 0;i < r_refdef.scene.numentities;i++)
4896                 {
4897                         ent = r_refdef.scene.entities[i];
4898                         if (!(ent->flags & renderimask))
4899                         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)))
4900                         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))
4901                                 r_refdef.viewcache.entityvisible[i] = true;
4902                 }
4903         }
4904         else
4905         {
4906                 // no worldmodel or it can't check visibility
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         ent = r_refdef.scene.entities[i];
4910                         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));
4911                 }
4912         }
4913         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4914                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4915         {
4916                 for (i = 0;i < r_refdef.scene.numentities;i++)
4917                 {
4918                         if (!r_refdef.viewcache.entityvisible[i])
4919                                 continue;
4920                         ent = r_refdef.scene.entities[i];
4921                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4922                         {
4923                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4924                                 if (samples < 0)
4925                                         continue; // temp entities do pvs only
4926                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4927                                         ent->last_trace_visibility = realtime;
4928                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4929                                         r_refdef.viewcache.entityvisible[i] = 0;
4930                         }
4931                 }
4932         }
4933 }
4934
4935 /// only used if skyrendermasked, and normally returns false
4936 static int R_DrawBrushModelsSky (void)
4937 {
4938         int i, sky;
4939         entity_render_t *ent;
4940
4941         sky = false;
4942         for (i = 0;i < r_refdef.scene.numentities;i++)
4943         {
4944                 if (!r_refdef.viewcache.entityvisible[i])
4945                         continue;
4946                 ent = r_refdef.scene.entities[i];
4947                 if (!ent->model || !ent->model->DrawSky)
4948                         continue;
4949                 ent->model->DrawSky(ent);
4950                 sky = true;
4951         }
4952         return sky;
4953 }
4954
4955 static void R_DrawNoModel(entity_render_t *ent);
4956 static void R_DrawModels(void)
4957 {
4958         int i;
4959         entity_render_t *ent;
4960
4961         for (i = 0;i < r_refdef.scene.numentities;i++)
4962         {
4963                 if (!r_refdef.viewcache.entityvisible[i])
4964                         continue;
4965                 ent = r_refdef.scene.entities[i];
4966                 r_refdef.stats.entities++;
4967                 /*
4968                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4969                 {
4970                         vec3_t f, l, u, o;
4971                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4972                         Con_Printf("R_DrawModels\n");
4973                         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]);
4974                         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);
4975                         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);
4976                 }
4977                 */
4978                 if (ent->model && ent->model->Draw != NULL)
4979                         ent->model->Draw(ent);
4980                 else
4981                         R_DrawNoModel(ent);
4982         }
4983 }
4984
4985 static void R_DrawModelsDepth(void)
4986 {
4987         int i;
4988         entity_render_t *ent;
4989
4990         for (i = 0;i < r_refdef.scene.numentities;i++)
4991         {
4992                 if (!r_refdef.viewcache.entityvisible[i])
4993                         continue;
4994                 ent = r_refdef.scene.entities[i];
4995                 if (ent->model && ent->model->DrawDepth != NULL)
4996                         ent->model->DrawDepth(ent);
4997         }
4998 }
4999
5000 static void R_DrawModelsDebug(void)
5001 {
5002         int i;
5003         entity_render_t *ent;
5004
5005         for (i = 0;i < r_refdef.scene.numentities;i++)
5006         {
5007                 if (!r_refdef.viewcache.entityvisible[i])
5008                         continue;
5009                 ent = r_refdef.scene.entities[i];
5010                 if (ent->model && ent->model->DrawDebug != NULL)
5011                         ent->model->DrawDebug(ent);
5012         }
5013 }
5014
5015 static void R_DrawModelsAddWaterPlanes(void)
5016 {
5017         int i;
5018         entity_render_t *ent;
5019
5020         for (i = 0;i < r_refdef.scene.numentities;i++)
5021         {
5022                 if (!r_refdef.viewcache.entityvisible[i])
5023                         continue;
5024                 ent = r_refdef.scene.entities[i];
5025                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5026                         ent->model->DrawAddWaterPlanes(ent);
5027         }
5028 }
5029
5030 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}};
5031
5032 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5033 {
5034         if (r_hdr_irisadaptation.integer)
5035         {
5036                 vec3_t p;
5037                 vec3_t ambient;
5038                 vec3_t diffuse;
5039                 vec3_t diffusenormal;
5040                 vec3_t forward;
5041                 vec_t brightness = 0.0f;
5042                 vec_t goal;
5043                 vec_t current;
5044                 vec_t d;
5045                 int c;
5046                 VectorCopy(r_refdef.view.forward, forward);
5047                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5048                 {
5049                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5050                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5051                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5052                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5053                         d = DotProduct(forward, diffusenormal);
5054                         brightness += VectorLength(ambient);
5055                         if (d > 0)
5056                                 brightness += d * VectorLength(diffuse);
5057                 }
5058                 brightness *= 1.0f / c;
5059                 brightness += 0.00001f; // make sure it's never zero
5060                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5061                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5062                 current = r_hdr_irisadaptation_value.value;
5063                 if (current < goal)
5064                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5065                 else if (current > goal)
5066                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5067                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5068                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5069         }
5070         else if (r_hdr_irisadaptation_value.value != 1.0f)
5071                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5072 }
5073
5074 static void R_View_SetFrustum(const int *scissor)
5075 {
5076         int i;
5077         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5078         vec3_t forward, left, up, origin, v;
5079
5080         if(scissor)
5081         {
5082                 // flipped x coordinates (because x points left here)
5083                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5084                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5085
5086                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5087                 switch(vid.renderpath)
5088                 {
5089                         case RENDERPATH_D3D9:
5090                         case RENDERPATH_D3D10:
5091                         case RENDERPATH_D3D11:
5092                                 // non-flipped y coordinates
5093                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5094                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5095                                 break;
5096                         case RENDERPATH_SOFT:
5097                         case RENDERPATH_GL11:
5098                         case RENDERPATH_GL13:
5099                         case RENDERPATH_GL20:
5100                         case RENDERPATH_GLES1:
5101                         case RENDERPATH_GLES2:
5102                                 // non-flipped y coordinates
5103                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5104                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5105                                 break;
5106                 }
5107         }
5108
5109         // we can't trust r_refdef.view.forward and friends in reflected scenes
5110         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5111
5112 #if 0
5113         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5114         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5115         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5116         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5117         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5118         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5119         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5120         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5121         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5122         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5123         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5124         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5125 #endif
5126
5127 #if 0
5128         zNear = r_refdef.nearclip;
5129         nudge = 1.0 - 1.0 / (1<<23);
5130         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5131         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5132         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5133         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5134         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5135         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5136         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5137         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5138 #endif
5139
5140
5141
5142 #if 0
5143         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5144         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5145         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5146         r_refdef.view.frustum[0].dist = m[15] - m[12];
5147
5148         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5149         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5150         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5151         r_refdef.view.frustum[1].dist = m[15] + m[12];
5152
5153         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5154         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5155         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5156         r_refdef.view.frustum[2].dist = m[15] - m[13];
5157
5158         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5159         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5160         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5161         r_refdef.view.frustum[3].dist = m[15] + m[13];
5162
5163         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5164         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5165         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5166         r_refdef.view.frustum[4].dist = m[15] - m[14];
5167
5168         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5169         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5170         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5171         r_refdef.view.frustum[5].dist = m[15] + m[14];
5172 #endif
5173
5174         if (r_refdef.view.useperspective)
5175         {
5176                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5177                 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]);
5178                 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]);
5179                 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]);
5180                 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]);
5181
5182                 // then the normals from the corners relative to origin
5183                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5184                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5185                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5186                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5187
5188                 // in a NORMAL view, forward cross left == up
5189                 // in a REFLECTED view, forward cross left == down
5190                 // so our cross products above need to be adjusted for a left handed coordinate system
5191                 CrossProduct(forward, left, v);
5192                 if(DotProduct(v, up) < 0)
5193                 {
5194                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5195                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5196                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5197                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5198                 }
5199
5200                 // Leaving those out was a mistake, those were in the old code, and they
5201                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5202                 // I couldn't reproduce it after adding those normalizations. --blub
5203                 VectorNormalize(r_refdef.view.frustum[0].normal);
5204                 VectorNormalize(r_refdef.view.frustum[1].normal);
5205                 VectorNormalize(r_refdef.view.frustum[2].normal);
5206                 VectorNormalize(r_refdef.view.frustum[3].normal);
5207
5208                 // make the corners absolute
5209                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5210                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5211                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5212                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5213
5214                 // one more normal
5215                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5216
5217                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5218                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5219                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5220                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5221                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5222         }
5223         else
5224         {
5225                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5226                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5227                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5228                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5229                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5230                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5231                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5232                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5233                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5234                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5235         }
5236         r_refdef.view.numfrustumplanes = 5;
5237
5238         if (r_refdef.view.useclipplane)
5239         {
5240                 r_refdef.view.numfrustumplanes = 6;
5241                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5242         }
5243
5244         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5245                 PlaneClassify(r_refdef.view.frustum + i);
5246
5247         // LordHavoc: note to all quake engine coders, Quake had a special case
5248         // for 90 degrees which assumed a square view (wrong), so I removed it,
5249         // Quake2 has it disabled as well.
5250
5251         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5252         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5253         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5254         //PlaneClassify(&frustum[0]);
5255
5256         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5257         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5258         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5259         //PlaneClassify(&frustum[1]);
5260
5261         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5262         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5263         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5264         //PlaneClassify(&frustum[2]);
5265
5266         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5267         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5268         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5269         //PlaneClassify(&frustum[3]);
5270
5271         // nearclip plane
5272         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5273         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5274         //PlaneClassify(&frustum[4]);
5275 }
5276
5277 static void R_View_UpdateWithScissor(const int *myscissor)
5278 {
5279         R_Main_ResizeViewCache();
5280         R_View_SetFrustum(myscissor);
5281         R_View_WorldVisibility(r_refdef.view.useclipplane);
5282         R_View_UpdateEntityVisible();
5283         R_View_UpdateEntityLighting();
5284 }
5285
5286 static void R_View_Update(void)
5287 {
5288         R_Main_ResizeViewCache();
5289         R_View_SetFrustum(NULL);
5290         R_View_WorldVisibility(r_refdef.view.useclipplane);
5291         R_View_UpdateEntityVisible();
5292         R_View_UpdateEntityLighting();
5293 }
5294
5295 float viewscalefpsadjusted = 1.0f;
5296
5297 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5298 {
5299         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5300         scale = bound(0.03125f, scale, 1.0f);
5301         *outwidth = (int)ceil(width * scale);
5302         *outheight = (int)ceil(height * scale);
5303 }
5304
5305 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5306 {
5307         const float *customclipplane = NULL;
5308         float plane[4];
5309         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5310         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5311         {
5312                 // LordHavoc: couldn't figure out how to make this approach the
5313                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5314                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5315                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5316                         dist = r_refdef.view.clipplane.dist;
5317                 plane[0] = r_refdef.view.clipplane.normal[0];
5318                 plane[1] = r_refdef.view.clipplane.normal[1];
5319                 plane[2] = r_refdef.view.clipplane.normal[2];
5320                 plane[3] = -dist;
5321                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5322         }
5323
5324         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5325         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5326
5327         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5328         if (!r_refdef.view.useperspective)
5329                 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);
5330         else if (vid.stencil && r_useinfinitefarclip.integer)
5331                 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);
5332         else
5333                 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);
5334         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5335         R_SetViewport(&r_refdef.view.viewport);
5336         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5337         {
5338                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5339                 float screenplane[4];
5340                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5341                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5342                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5343                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5344                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5345         }
5346 }
5347
5348 void R_EntityMatrix(const matrix4x4_t *matrix)
5349 {
5350         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5351         {
5352                 gl_modelmatrixchanged = false;
5353                 gl_modelmatrix = *matrix;
5354                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5355                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5356                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5357                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5358                 CHECKGLERROR
5359                 switch(vid.renderpath)
5360                 {
5361                 case RENDERPATH_D3D9:
5362 #ifdef SUPPORTD3D
5363                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5364                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5365 #endif
5366                         break;
5367                 case RENDERPATH_D3D10:
5368                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5369                         break;
5370                 case RENDERPATH_D3D11:
5371                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5372                         break;
5373                 case RENDERPATH_GL11:
5374                 case RENDERPATH_GL13:
5375                 case RENDERPATH_GLES1:
5376                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5377                         break;
5378                 case RENDERPATH_SOFT:
5379                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5380                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5381                         break;
5382                 case RENDERPATH_GL20:
5383                 case RENDERPATH_GLES2:
5384                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5385                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5386                         break;
5387                 }
5388         }
5389 }
5390
5391 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5392 {
5393         r_viewport_t viewport;
5394
5395         CHECKGLERROR
5396
5397         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5398         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5399         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5400         R_SetViewport(&viewport);
5401         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5402         GL_Color(1, 1, 1, 1);
5403         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5404         GL_BlendFunc(GL_ONE, GL_ZERO);
5405         GL_ScissorTest(false);
5406         GL_DepthMask(false);
5407         GL_DepthRange(0, 1);
5408         GL_DepthTest(false);
5409         GL_DepthFunc(GL_LEQUAL);
5410         R_EntityMatrix(&identitymatrix);
5411         R_Mesh_ResetTextureState();
5412         GL_PolygonOffset(0, 0);
5413         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5414         switch(vid.renderpath)
5415         {
5416         case RENDERPATH_GL11:
5417         case RENDERPATH_GL13:
5418         case RENDERPATH_GL20:
5419         case RENDERPATH_GLES1:
5420         case RENDERPATH_GLES2:
5421                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5422                 break;
5423         case RENDERPATH_D3D9:
5424         case RENDERPATH_D3D10:
5425         case RENDERPATH_D3D11:
5426         case RENDERPATH_SOFT:
5427                 break;
5428         }
5429         GL_CullFace(GL_NONE);
5430
5431         CHECKGLERROR
5432 }
5433
5434 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5435 {
5436         DrawQ_Finish();
5437
5438         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5439 }
5440
5441 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5442 {
5443         DrawQ_Finish();
5444
5445         R_SetupView(true, fbo, depthtexture, colortexture);
5446         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5447         GL_Color(1, 1, 1, 1);
5448         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5449         GL_BlendFunc(GL_ONE, GL_ZERO);
5450         GL_ScissorTest(true);
5451         GL_DepthMask(true);
5452         GL_DepthRange(0, 1);
5453         GL_DepthTest(true);
5454         GL_DepthFunc(GL_LEQUAL);
5455         R_EntityMatrix(&identitymatrix);
5456         R_Mesh_ResetTextureState();
5457         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5458         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5459         switch(vid.renderpath)
5460         {
5461         case RENDERPATH_GL11:
5462         case RENDERPATH_GL13:
5463         case RENDERPATH_GL20:
5464         case RENDERPATH_GLES1:
5465         case RENDERPATH_GLES2:
5466                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5467                 break;
5468         case RENDERPATH_D3D9:
5469         case RENDERPATH_D3D10:
5470         case RENDERPATH_D3D11:
5471         case RENDERPATH_SOFT:
5472                 break;
5473         }
5474         GL_CullFace(r_refdef.view.cullface_back);
5475 }
5476
5477 /*
5478 ================
5479 R_RenderView_UpdateViewVectors
5480 ================
5481 */
5482 void R_RenderView_UpdateViewVectors(void)
5483 {
5484         // break apart the view matrix into vectors for various purposes
5485         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5486         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5487         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5488         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5489         // make an inverted copy of the view matrix for tracking sprites
5490         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5491 }
5492
5493 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5494 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5495
5496 static void R_Water_StartFrame(void)
5497 {
5498         int i;
5499         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5500         r_waterstate_waterplane_t *p;
5501         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5502
5503         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5504                 return;
5505
5506         switch(vid.renderpath)
5507         {
5508         case RENDERPATH_GL20:
5509         case RENDERPATH_D3D9:
5510         case RENDERPATH_D3D10:
5511         case RENDERPATH_D3D11:
5512         case RENDERPATH_SOFT:
5513         case RENDERPATH_GLES2:
5514                 break;
5515         case RENDERPATH_GL11:
5516         case RENDERPATH_GL13:
5517         case RENDERPATH_GLES1:
5518                 return;
5519         }
5520
5521         // set waterwidth and waterheight to the water resolution that will be
5522         // used (often less than the screen resolution for faster rendering)
5523         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5524
5525         // calculate desired texture sizes
5526         // can't use water if the card does not support the texture size
5527         if (!r_water.integer || r_showsurfaces.integer)
5528                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5529         else if (vid.support.arb_texture_non_power_of_two)
5530         {
5531                 texturewidth = waterwidth;
5532                 textureheight = waterheight;
5533                 camerawidth = waterwidth;
5534                 cameraheight = waterheight;
5535         }
5536         else
5537         {
5538                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5539                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5540                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5541                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5542         }
5543
5544         // allocate textures as needed
5545         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))
5546         {
5547                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5548                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5549                 {
5550                         if (p->texture_refraction)
5551                                 R_FreeTexture(p->texture_refraction);
5552                         p->texture_refraction = NULL;
5553                         if (p->fbo_refraction)
5554                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5555                         p->fbo_refraction = 0;
5556                         if (p->texture_reflection)
5557                                 R_FreeTexture(p->texture_reflection);
5558                         p->texture_reflection = NULL;
5559                         if (p->fbo_reflection)
5560                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5561                         p->fbo_reflection = 0;
5562                         if (p->texture_camera)
5563                                 R_FreeTexture(p->texture_camera);
5564                         p->texture_camera = NULL;
5565                         if (p->fbo_camera)
5566                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5567                         p->fbo_camera = 0;
5568                 }
5569                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5570                 r_fb.water.texturewidth = texturewidth;
5571                 r_fb.water.textureheight = textureheight;
5572                 r_fb.water.camerawidth = camerawidth;
5573                 r_fb.water.cameraheight = cameraheight;
5574         }
5575
5576         if (r_fb.water.texturewidth)
5577         {
5578                 int scaledwidth, scaledheight;
5579
5580                 r_fb.water.enabled = true;
5581
5582                 // water resolution is usually reduced
5583                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5584                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5585                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5586
5587                 // set up variables that will be used in shader setup
5588                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5589                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5590                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5591                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5592         }
5593
5594         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5595         r_fb.water.numwaterplanes = 0;
5596 }
5597
5598 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5599 {
5600         int planeindex, bestplaneindex, vertexindex;
5601         vec3_t mins, maxs, normal, center, v, n;
5602         vec_t planescore, bestplanescore;
5603         mplane_t plane;
5604         r_waterstate_waterplane_t *p;
5605         texture_t *t = R_GetCurrentTexture(surface->texture);
5606
5607         rsurface.texture = t;
5608         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5609         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5610         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5611                 return;
5612         // average the vertex normals, find the surface bounds (after deformvertexes)
5613         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5614         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5615         VectorCopy(n, normal);
5616         VectorCopy(v, mins);
5617         VectorCopy(v, maxs);
5618         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5619         {
5620                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5621                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5622                 VectorAdd(normal, n, normal);
5623                 mins[0] = min(mins[0], v[0]);
5624                 mins[1] = min(mins[1], v[1]);
5625                 mins[2] = min(mins[2], v[2]);
5626                 maxs[0] = max(maxs[0], v[0]);
5627                 maxs[1] = max(maxs[1], v[1]);
5628                 maxs[2] = max(maxs[2], v[2]);
5629         }
5630         VectorNormalize(normal);
5631         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5632
5633         VectorCopy(normal, plane.normal);
5634         VectorNormalize(plane.normal);
5635         plane.dist = DotProduct(center, plane.normal);
5636         PlaneClassify(&plane);
5637         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5638         {
5639                 // skip backfaces (except if nocullface is set)
5640 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5641 //                      return;
5642                 VectorNegate(plane.normal, plane.normal);
5643                 plane.dist *= -1;
5644                 PlaneClassify(&plane);
5645         }
5646
5647
5648         // find a matching plane if there is one
5649         bestplaneindex = -1;
5650         bestplanescore = 1048576.0f;
5651         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5652         {
5653                 if(p->camera_entity == t->camera_entity)
5654                 {
5655                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5656                         if (bestplaneindex < 0 || bestplanescore > planescore)
5657                         {
5658                                 bestplaneindex = planeindex;
5659                                 bestplanescore = planescore;
5660                         }
5661                 }
5662         }
5663         planeindex = bestplaneindex;
5664         p = r_fb.water.waterplanes + planeindex;
5665
5666         // if this surface does not fit any known plane rendered this frame, add one
5667         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5668         {
5669                 // store the new plane
5670                 planeindex = r_fb.water.numwaterplanes++;
5671                 p = r_fb.water.waterplanes + planeindex;
5672                 p->plane = plane;
5673                 // clear materialflags and pvs
5674                 p->materialflags = 0;
5675                 p->pvsvalid = false;
5676                 p->camera_entity = t->camera_entity;
5677                 VectorCopy(mins, p->mins);
5678                 VectorCopy(maxs, p->maxs);
5679         }
5680         else
5681         {
5682                 // merge mins/maxs when we're adding this surface to the plane
5683                 p->mins[0] = min(p->mins[0], mins[0]);
5684                 p->mins[1] = min(p->mins[1], mins[1]);
5685                 p->mins[2] = min(p->mins[2], mins[2]);
5686                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5687                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5688                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5689         }
5690         // merge this surface's materialflags into the waterplane
5691         p->materialflags |= t->currentmaterialflags;
5692         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5693         {
5694                 // merge this surface's PVS into the waterplane
5695                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5696                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5697                 {
5698                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5699                         p->pvsvalid = true;
5700                 }
5701         }
5702 }
5703
5704 extern cvar_t r_drawparticles;
5705 extern cvar_t r_drawdecals;
5706
5707 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5708 {
5709         int myscissor[4];
5710         r_refdef_view_t originalview;
5711         r_refdef_view_t myview;
5712         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;
5713         r_waterstate_waterplane_t *p;
5714         vec3_t visorigin;
5715         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5716         char vabuf[1024];
5717
5718         originalview = r_refdef.view;
5719
5720         // lowquality hack, temporarily shut down some cvars and restore afterwards
5721         qualityreduction = r_water_lowquality.integer;
5722         if (qualityreduction > 0)
5723         {
5724                 if (qualityreduction >= 1)
5725                 {
5726                         old_r_shadows = r_shadows.integer;
5727                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5728                         old_r_dlight = r_shadow_realtime_dlight.integer;
5729                         Cvar_SetValueQuick(&r_shadows, 0);
5730                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5731                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5732                 }
5733                 if (qualityreduction >= 2)
5734                 {
5735                         old_r_dynamic = r_dynamic.integer;
5736                         old_r_particles = r_drawparticles.integer;
5737                         old_r_decals = r_drawdecals.integer;
5738                         Cvar_SetValueQuick(&r_dynamic, 0);
5739                         Cvar_SetValueQuick(&r_drawparticles, 0);
5740                         Cvar_SetValueQuick(&r_drawdecals, 0);
5741                 }
5742         }
5743
5744         // make sure enough textures are allocated
5745         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5746         {
5747                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5748                 {
5749                         if (!p->texture_refraction)
5750                                 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);
5751                         if (!p->texture_refraction)
5752                                 goto error;
5753                         if (usewaterfbo)
5754                         {
5755                                 if (r_fb.water.depthtexture == NULL)
5756                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5757                                 if (p->fbo_refraction == 0)
5758                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5759                         }
5760                 }
5761                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5762                 {
5763                         if (!p->texture_camera)
5764                                 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);
5765                         if (!p->texture_camera)
5766                                 goto error;
5767                         if (usewaterfbo)
5768                         {
5769                                 if (r_fb.water.depthtexture == NULL)
5770                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5771                                 if (p->fbo_camera == 0)
5772                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5773                         }
5774                 }
5775
5776                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5777                 {
5778                         if (!p->texture_reflection)
5779                                 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);
5780                         if (!p->texture_reflection)
5781                                 goto error;
5782                         if (usewaterfbo)
5783                         {
5784                                 if (r_fb.water.depthtexture == NULL)
5785                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5786                                 if (p->fbo_reflection == 0)
5787                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5788                         }
5789                 }
5790         }
5791
5792         // render views
5793         r_refdef.view = originalview;
5794         r_refdef.view.showdebug = false;
5795         r_refdef.view.width = r_fb.water.waterwidth;
5796         r_refdef.view.height = r_fb.water.waterheight;
5797         r_refdef.view.useclipplane = true;
5798         myview = r_refdef.view;
5799         r_fb.water.renderingscene = true;
5800         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5801         {
5802                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5803                 {
5804                         r_refdef.view = myview;
5805                         if(r_water_scissormode.integer)
5806                         {
5807                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5808                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5809                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5810                         }
5811
5812                         // render reflected scene and copy into texture
5813                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5814                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5815                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5816                         r_refdef.view.clipplane = p->plane;
5817                         // reverse the cullface settings for this render
5818                         r_refdef.view.cullface_front = GL_FRONT;
5819                         r_refdef.view.cullface_back = GL_BACK;
5820                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5821                         {
5822                                 r_refdef.view.usecustompvs = true;
5823                                 if (p->pvsvalid)
5824                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5825                                 else
5826                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5827                         }
5828
5829                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5830                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5831                         R_ClearScreen(r_refdef.fogenabled);
5832                         if(r_water_scissormode.integer & 2)
5833                                 R_View_UpdateWithScissor(myscissor);
5834                         else
5835                                 R_View_Update();
5836                         R_AnimCache_CacheVisibleEntities();
5837                         if(r_water_scissormode.integer & 1)
5838                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5839                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5840
5841                         if (!p->fbo_reflection)
5842                                 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);
5843                         r_fb.water.hideplayer = false;
5844                 }
5845
5846                 // render the normal view scene and copy into texture
5847                 // (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)
5848                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5849                 {
5850                         r_refdef.view = myview;
5851                         if(r_water_scissormode.integer)
5852                         {
5853                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5854                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5855                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5856                         }
5857
5858                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5859
5860                         r_refdef.view.clipplane = p->plane;
5861                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5862                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5863
5864                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5865                         {
5866                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5867                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5868                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5869                                 R_RenderView_UpdateViewVectors();
5870                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5871                                 {
5872                                         r_refdef.view.usecustompvs = true;
5873                                         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);
5874                                 }
5875                         }
5876
5877                         PlaneClassify(&r_refdef.view.clipplane);
5878
5879                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5880                         R_ClearScreen(r_refdef.fogenabled);
5881                         if(r_water_scissormode.integer & 2)
5882                                 R_View_UpdateWithScissor(myscissor);
5883                         else
5884                                 R_View_Update();
5885                         R_AnimCache_CacheVisibleEntities();
5886                         if(r_water_scissormode.integer & 1)
5887                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5888                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5889
5890                         if (!p->fbo_refraction)
5891                                 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);
5892                         r_fb.water.hideplayer = false;
5893                 }
5894                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5895                 {
5896                         r_refdef.view = myview;
5897
5898                         r_refdef.view.clipplane = p->plane;
5899                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5900                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5901
5902                         r_refdef.view.width = r_fb.water.camerawidth;
5903                         r_refdef.view.height = r_fb.water.cameraheight;
5904                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5905                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5906                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5907                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5908
5909                         if(p->camera_entity)
5910                         {
5911                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5912                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5913                         }
5914
5915                         // note: all of the view is used for displaying... so
5916                         // there is no use in scissoring
5917
5918                         // reverse the cullface settings for this render
5919                         r_refdef.view.cullface_front = GL_FRONT;
5920                         r_refdef.view.cullface_back = GL_BACK;
5921                         // also reverse the view matrix
5922                         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
5923                         R_RenderView_UpdateViewVectors();
5924                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5925                         {
5926                                 r_refdef.view.usecustompvs = true;
5927                                 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);
5928                         }
5929                         
5930                         // camera needs no clipplane
5931                         r_refdef.view.useclipplane = false;
5932
5933                         PlaneClassify(&r_refdef.view.clipplane);
5934
5935                         r_fb.water.hideplayer = false;
5936
5937                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5938                         R_ClearScreen(r_refdef.fogenabled);
5939                         R_View_Update();
5940                         R_AnimCache_CacheVisibleEntities();
5941                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5942
5943                         if (!p->fbo_camera)
5944                                 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);
5945                         r_fb.water.hideplayer = false;
5946                 }
5947
5948         }
5949         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5950         r_fb.water.renderingscene = false;
5951         r_refdef.view = originalview;
5952         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5953         if (!r_fb.water.depthtexture)
5954                 R_ClearScreen(r_refdef.fogenabled);
5955         R_View_Update();
5956         R_AnimCache_CacheVisibleEntities();
5957         goto finish;
5958 error:
5959         r_refdef.view = originalview;
5960         r_fb.water.renderingscene = false;
5961         Cvar_SetValueQuick(&r_water, 0);
5962         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5963 finish:
5964         // lowquality hack, restore cvars
5965         if (qualityreduction > 0)
5966         {
5967                 if (qualityreduction >= 1)
5968                 {
5969                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5970                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5971                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5972                 }
5973                 if (qualityreduction >= 2)
5974                 {
5975                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5976                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5977                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5978                 }
5979         }
5980 }
5981
5982 static void R_Bloom_StartFrame(void)
5983 {
5984         int i;
5985         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5986         int viewwidth, viewheight;
5987         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5988         textype_t textype = TEXTYPE_COLORBUFFER;
5989
5990         switch (vid.renderpath)
5991         {
5992         case RENDERPATH_GL20:
5993                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5994                 if (vid.support.ext_framebuffer_object)
5995                 {
5996                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5997                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5998                 }
5999                 break;
6000         case RENDERPATH_GL11:
6001         case RENDERPATH_GL13:
6002         case RENDERPATH_GLES1:
6003         case RENDERPATH_GLES2:
6004         case RENDERPATH_D3D9:
6005         case RENDERPATH_D3D10:
6006         case RENDERPATH_D3D11:
6007                 r_fb.usedepthtextures = false;
6008                 break;
6009         case RENDERPATH_SOFT:
6010                 r_fb.usedepthtextures = true;
6011                 break;
6012         }
6013
6014         if (r_viewscale_fpsscaling.integer)
6015         {
6016                 double actualframetime;
6017                 double targetframetime;
6018                 double adjust;
6019                 actualframetime = r_refdef.lastdrawscreentime;
6020                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6021                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6022                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6023                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6024                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6025                 viewscalefpsadjusted += adjust;
6026                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6027         }
6028         else
6029                 viewscalefpsadjusted = 1.0f;
6030
6031         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6032
6033         switch(vid.renderpath)
6034         {
6035         case RENDERPATH_GL20:
6036         case RENDERPATH_D3D9:
6037         case RENDERPATH_D3D10:
6038         case RENDERPATH_D3D11:
6039         case RENDERPATH_SOFT:
6040         case RENDERPATH_GLES2:
6041                 break;
6042         case RENDERPATH_GL11:
6043         case RENDERPATH_GL13:
6044         case RENDERPATH_GLES1:
6045                 return;
6046         }
6047
6048         // set bloomwidth and bloomheight to the bloom resolution that will be
6049         // used (often less than the screen resolution for faster rendering)
6050         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6051         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6052         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6053         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6054         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6055
6056         // calculate desired texture sizes
6057         if (vid.support.arb_texture_non_power_of_two)
6058         {
6059                 screentexturewidth = vid.width;
6060                 screentextureheight = vid.height;
6061                 bloomtexturewidth = r_fb.bloomwidth;
6062                 bloomtextureheight = r_fb.bloomheight;
6063         }
6064         else
6065         {
6066                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6067                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6068                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6069                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6070         }
6071
6072         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))
6073         {
6074                 Cvar_SetValueQuick(&r_bloom, 0);
6075                 Cvar_SetValueQuick(&r_motionblur, 0);
6076                 Cvar_SetValueQuick(&r_damageblur, 0);
6077         }
6078
6079         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6080          && !r_bloom.integer
6081          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6082          && !useviewfbo
6083          && r_viewscale.value == 1.0f
6084          && !r_viewscale_fpsscaling.integer)
6085                 screentexturewidth = screentextureheight = 0;
6086         if (!r_bloom.integer)
6087                 bloomtexturewidth = bloomtextureheight = 0;
6088
6089         // allocate textures as needed
6090         if (r_fb.screentexturewidth != screentexturewidth
6091          || r_fb.screentextureheight != screentextureheight
6092          || r_fb.bloomtexturewidth != bloomtexturewidth
6093          || r_fb.bloomtextureheight != bloomtextureheight
6094          || r_fb.textype != textype
6095          || useviewfbo != (r_fb.fbo != 0))
6096         {
6097                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6098                 {
6099                         if (r_fb.bloomtexture[i])
6100                                 R_FreeTexture(r_fb.bloomtexture[i]);
6101                         r_fb.bloomtexture[i] = NULL;
6102
6103                         if (r_fb.bloomfbo[i])
6104                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6105                         r_fb.bloomfbo[i] = 0;
6106                 }
6107
6108                 if (r_fb.fbo)
6109                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6110                 r_fb.fbo = 0;
6111
6112                 if (r_fb.colortexture)
6113                         R_FreeTexture(r_fb.colortexture);
6114                 r_fb.colortexture = NULL;
6115
6116                 if (r_fb.depthtexture)
6117                         R_FreeTexture(r_fb.depthtexture);
6118                 r_fb.depthtexture = NULL;
6119
6120                 if (r_fb.ghosttexture)
6121                         R_FreeTexture(r_fb.ghosttexture);
6122                 r_fb.ghosttexture = NULL;
6123
6124                 r_fb.screentexturewidth = screentexturewidth;
6125                 r_fb.screentextureheight = screentextureheight;
6126                 r_fb.bloomtexturewidth = bloomtexturewidth;
6127                 r_fb.bloomtextureheight = bloomtextureheight;
6128                 r_fb.textype = textype;
6129
6130                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6131                 {
6132                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6133                                 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);
6134                         r_fb.ghosttexture_valid = false;
6135                         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);
6136                         if (useviewfbo)
6137                         {
6138                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6139                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6140                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6141                         }
6142                 }
6143
6144                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6145                 {
6146                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6147                         {
6148                                 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);
6149                                 if (useviewfbo)
6150                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6151                         }
6152                 }
6153         }
6154
6155         // bloom texture is a different resolution
6156         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6157         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6158         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6159         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6160         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6161
6162         // set up a texcoord array for the full resolution screen image
6163         // (we have to keep this around to copy back during final render)
6164         r_fb.screentexcoord2f[0] = 0;
6165         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6166         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6167         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6168         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6169         r_fb.screentexcoord2f[5] = 0;
6170         r_fb.screentexcoord2f[6] = 0;
6171         r_fb.screentexcoord2f[7] = 0;
6172
6173         if(r_fb.fbo) 
6174         {
6175                 for (i = 1;i < 8;i += 2)
6176                 {
6177                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6178                 }
6179         }
6180
6181         // set up a texcoord array for the reduced resolution bloom image
6182         // (which will be additive blended over the screen image)
6183         r_fb.bloomtexcoord2f[0] = 0;
6184         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6185         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6186         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6187         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6188         r_fb.bloomtexcoord2f[5] = 0;
6189         r_fb.bloomtexcoord2f[6] = 0;
6190         r_fb.bloomtexcoord2f[7] = 0;
6191
6192         switch(vid.renderpath)
6193         {
6194         case RENDERPATH_GL11:
6195         case RENDERPATH_GL13:
6196         case RENDERPATH_GL20:
6197         case RENDERPATH_SOFT:
6198         case RENDERPATH_GLES1:
6199         case RENDERPATH_GLES2:
6200                 break;
6201         case RENDERPATH_D3D9:
6202         case RENDERPATH_D3D10:
6203         case RENDERPATH_D3D11:
6204                 for (i = 0;i < 4;i++)
6205                 {
6206                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6207                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6208                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6209                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6210                 }
6211                 break;
6212         }
6213
6214         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6215
6216         if (r_fb.fbo)
6217                 r_refdef.view.clear = true;
6218 }
6219
6220 static void R_Bloom_MakeTexture(void)
6221 {
6222         int x, range, dir;
6223         float xoffset, yoffset, r, brighten;
6224         rtexture_t *intex;
6225         float colorscale = r_bloom_colorscale.value;
6226
6227         r_refdef.stats.bloom++;
6228     
6229 #if 0
6230     // this copy is unnecessary since it happens in R_BlendView already
6231         if (!r_fb.fbo)
6232         {
6233                 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);
6234                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6235         }
6236 #endif
6237
6238         // scale down screen texture to the bloom texture size
6239         CHECKGLERROR
6240         r_fb.bloomindex = 0;
6241         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6242         R_SetViewport(&r_fb.bloomviewport);
6243         GL_DepthTest(false);
6244         GL_BlendFunc(GL_ONE, GL_ZERO);
6245         GL_Color(colorscale, colorscale, colorscale, 1);
6246         // 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...
6247         switch(vid.renderpath)
6248         {
6249         case RENDERPATH_GL11:
6250         case RENDERPATH_GL13:
6251         case RENDERPATH_GL20:
6252         case RENDERPATH_GLES1:
6253         case RENDERPATH_GLES2:
6254         case RENDERPATH_SOFT:
6255                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6256                 break;
6257         case RENDERPATH_D3D9:
6258         case RENDERPATH_D3D10:
6259         case RENDERPATH_D3D11:
6260                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6261                 break;
6262         }
6263         // TODO: do boxfilter scale-down in shader?
6264         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6265         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6266         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6267
6268         // we now have a properly scaled bloom image
6269         if (!r_fb.bloomfbo[r_fb.bloomindex])
6270         {
6271                 // copy it into the bloom texture
6272                 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);
6273                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6274         }
6275
6276         // multiply bloom image by itself as many times as desired
6277         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6278         {
6279                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6280                 r_fb.bloomindex ^= 1;
6281                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6282                 x *= 2;
6283                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6284                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6285                 {
6286                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6287                         GL_Color(r,r,r,1); // apply fix factor
6288                 }
6289                 else
6290                 {
6291                         if(x <= 2)
6292                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6293                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6294                         GL_Color(1,1,1,1); // no fix factor supported here
6295                 }
6296                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6297                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6298                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6299                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6300
6301                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6302                 {
6303                         // copy the darkened image to a texture
6304                         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);
6305                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6306                 }
6307         }
6308
6309         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6310         brighten = r_bloom_brighten.value;
6311         brighten = sqrt(brighten);
6312         if(range >= 1)
6313                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6314
6315         for (dir = 0;dir < 2;dir++)
6316         {
6317                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6318                 r_fb.bloomindex ^= 1;
6319                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6320                 // blend on at multiple vertical offsets to achieve a vertical blur
6321                 // TODO: do offset blends using GLSL
6322                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6323                 GL_BlendFunc(GL_ONE, GL_ZERO);
6324                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6325                 for (x = -range;x <= range;x++)
6326                 {
6327                         if (!dir){xoffset = 0;yoffset = x;}
6328                         else {xoffset = x;yoffset = 0;}
6329                         xoffset /= (float)r_fb.bloomtexturewidth;
6330                         yoffset /= (float)r_fb.bloomtextureheight;
6331                         // compute a texcoord array with the specified x and y offset
6332                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6333                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6334                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6335                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6336                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6337                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6338                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6339                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6340                         // this r value looks like a 'dot' particle, fading sharply to
6341                         // black at the edges
6342                         // (probably not realistic but looks good enough)
6343                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6344                         //r = brighten/(range*2+1);
6345                         r = brighten / (range * 2 + 1);
6346                         if(range >= 1)
6347                                 r *= (1 - x*x/(float)(range*range));
6348                         GL_Color(r, r, r, 1);
6349                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6350                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6351                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6352                         GL_BlendFunc(GL_ONE, GL_ONE);
6353                 }
6354
6355                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6356                 {
6357                         // copy the vertically or horizontally blurred bloom view to a texture
6358                         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);
6359                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6360                 }
6361         }
6362 }
6363
6364 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6365 {
6366         unsigned int permutation;
6367         float uservecs[4][4];
6368
6369         switch (vid.renderpath)
6370         {
6371         case RENDERPATH_GL20:
6372         case RENDERPATH_D3D9:
6373         case RENDERPATH_D3D10:
6374         case RENDERPATH_D3D11:
6375         case RENDERPATH_SOFT:
6376         case RENDERPATH_GLES2:
6377                 permutation =
6378                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6379                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6380                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6381                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6382                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6383
6384                 if (r_fb.colortexture)
6385                 {
6386                         if (!r_fb.fbo)
6387                         {
6388                                 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);
6389                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6390                         }
6391
6392                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6393                         {
6394                                 // declare variables
6395                                 float blur_factor, blur_mouseaccel, blur_velocity;
6396                                 static float blur_average; 
6397                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6398
6399                                 // set a goal for the factoring
6400                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6401                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6402                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6403                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6404                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6405                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6406
6407                                 // from the goal, pick an averaged value between goal and last value
6408                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6409                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6410
6411                                 // enforce minimum amount of blur 
6412                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6413
6414                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6415
6416                                 // calculate values into a standard alpha
6417                                 cl.motionbluralpha = 1 - exp(-
6418                                                 (
6419                                                  (r_motionblur.value * blur_factor / 80)
6420                                                  +
6421                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6422                                                 )
6423                                                 /
6424                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6425                                           );
6426
6427                                 // randomization for the blur value to combat persistent ghosting
6428                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6429                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6430
6431                                 // apply the blur
6432                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6433                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6434                                 {
6435                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6436                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6437                                         switch(vid.renderpath)
6438                                         {
6439                                         case RENDERPATH_GL11:
6440                                         case RENDERPATH_GL13:
6441                                         case RENDERPATH_GL20:
6442                                         case RENDERPATH_GLES1:
6443                                         case RENDERPATH_GLES2:
6444                                         case RENDERPATH_SOFT:
6445                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6446                                                 break;
6447                                         case RENDERPATH_D3D9:
6448                                         case RENDERPATH_D3D10:
6449                                         case RENDERPATH_D3D11:
6450                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6451                                                 break;
6452                                         }
6453                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6454                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6455                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6456                                 }
6457
6458                                 // updates old view angles for next pass
6459                                 VectorCopy(cl.viewangles, blur_oldangles);
6460
6461                                 // copy view into the ghost texture
6462                                 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);
6463                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6464                                 r_fb.ghosttexture_valid = true;
6465                         }
6466                 }
6467                 else
6468                 {
6469                         // no r_fb.colortexture means we're rendering to the real fb
6470                         // we may still have to do view tint...
6471                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6472                         {
6473                                 // apply a color tint to the whole view
6474                                 R_ResetViewRendering2D(0, NULL, NULL);
6475                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6476                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6477                                 R_SetupShader_Generic_NoTexture(false, true);
6478                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6479                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6480                         }
6481                         break; // no screen processing, no bloom, skip it
6482                 }
6483
6484                 if (r_fb.bloomtexture[0])
6485                 {
6486                         // make the bloom texture
6487                         R_Bloom_MakeTexture();
6488                 }
6489
6490 #if _MSC_VER >= 1400
6491 #define sscanf sscanf_s
6492 #endif
6493                 memset(uservecs, 0, sizeof(uservecs));
6494                 if (r_glsl_postprocess_uservec1_enable.integer)
6495                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6496                 if (r_glsl_postprocess_uservec2_enable.integer)
6497                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6498                 if (r_glsl_postprocess_uservec3_enable.integer)
6499                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6500                 if (r_glsl_postprocess_uservec4_enable.integer)
6501                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6502
6503                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6504                 GL_Color(1, 1, 1, 1);
6505                 GL_BlendFunc(GL_ONE, GL_ZERO);
6506
6507                 switch(vid.renderpath)
6508                 {
6509                 case RENDERPATH_GL20:
6510                 case RENDERPATH_GLES2:
6511                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6512                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6513                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6514                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6515                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6516                         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]);
6517                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6518                         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]);
6519                         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]);
6520                         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]);
6521                         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]);
6522                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6523                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6524                         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);
6525                         break;
6526                 case RENDERPATH_D3D9:
6527 #ifdef SUPPORTD3D
6528                         // 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...
6529                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6530                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6531                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6532                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6533                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6534                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6535                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6536                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6537                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6538                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6539                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6540                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6541                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6542                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6543 #endif
6544                         break;
6545                 case RENDERPATH_D3D10:
6546                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6547                         break;
6548                 case RENDERPATH_D3D11:
6549                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6550                         break;
6551                 case RENDERPATH_SOFT:
6552                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6553                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6554                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6555                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6556                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6557                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6558                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6559                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6560                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6561                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6562                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6563                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6564                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6565                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6566                         break;
6567                 default:
6568                         break;
6569                 }
6570                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6571                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6572                 break;
6573         case RENDERPATH_GL11:
6574         case RENDERPATH_GL13:
6575         case RENDERPATH_GLES1:
6576                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6577                 {
6578                         // apply a color tint to the whole view
6579                         R_ResetViewRendering2D(0, NULL, NULL);
6580                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6581                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6582                         R_SetupShader_Generic_NoTexture(false, true);
6583                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6584                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6585                 }
6586                 break;
6587         }
6588 }
6589
6590 matrix4x4_t r_waterscrollmatrix;
6591
6592 void R_UpdateFog(void)
6593 {
6594         // Nehahra fog
6595         if (gamemode == GAME_NEHAHRA)
6596         {
6597                 if (gl_fogenable.integer)
6598                 {
6599                         r_refdef.oldgl_fogenable = true;
6600                         r_refdef.fog_density = gl_fogdensity.value;
6601                         r_refdef.fog_red = gl_fogred.value;
6602                         r_refdef.fog_green = gl_foggreen.value;
6603                         r_refdef.fog_blue = gl_fogblue.value;
6604                         r_refdef.fog_alpha = 1;
6605                         r_refdef.fog_start = 0;
6606                         r_refdef.fog_end = gl_skyclip.value;
6607                         r_refdef.fog_height = 1<<30;
6608                         r_refdef.fog_fadedepth = 128;
6609                 }
6610                 else if (r_refdef.oldgl_fogenable)
6611                 {
6612                         r_refdef.oldgl_fogenable = false;
6613                         r_refdef.fog_density = 0;
6614                         r_refdef.fog_red = 0;
6615                         r_refdef.fog_green = 0;
6616                         r_refdef.fog_blue = 0;
6617                         r_refdef.fog_alpha = 0;
6618                         r_refdef.fog_start = 0;
6619                         r_refdef.fog_end = 0;
6620                         r_refdef.fog_height = 1<<30;
6621                         r_refdef.fog_fadedepth = 128;
6622                 }
6623         }
6624
6625         // fog parms
6626         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6627         r_refdef.fog_start = max(0, r_refdef.fog_start);
6628         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6629
6630         if (r_refdef.fog_density && r_drawfog.integer)
6631         {
6632                 r_refdef.fogenabled = true;
6633                 // this is the point where the fog reaches 0.9986 alpha, which we
6634                 // consider a good enough cutoff point for the texture
6635                 // (0.9986 * 256 == 255.6)
6636                 if (r_fog_exp2.integer)
6637                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6638                 else
6639                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6640                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6641                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6642                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6643                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6644                         R_BuildFogHeightTexture();
6645                 // fog color was already set
6646                 // update the fog texture
6647                 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)
6648                         R_BuildFogTexture();
6649                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6650                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6651         }
6652         else
6653                 r_refdef.fogenabled = false;
6654
6655         // fog color
6656         if (r_refdef.fog_density)
6657         {
6658                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6659                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6660                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6661
6662                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6663                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6664                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6665                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6666
6667                 {
6668                         vec3_t fogvec;
6669                         VectorCopy(r_refdef.fogcolor, fogvec);
6670                         //   color.rgb *= ContrastBoost * SceneBrightness;
6671                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6672                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6673                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6674                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6675                 }
6676         }
6677 }
6678
6679 void R_UpdateVariables(void)
6680 {
6681         R_Textures_Frame();
6682
6683         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6684
6685         r_refdef.farclip = r_farclip_base.value;
6686         if (r_refdef.scene.worldmodel)
6687                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6688         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6689
6690         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6691                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6692         r_refdef.polygonfactor = 0;
6693         r_refdef.polygonoffset = 0;
6694         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6695         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6696
6697         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6698         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6699         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6700         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6701         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6702         if (FAKELIGHT_ENABLED)
6703         {
6704                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6705         }
6706         else if (r_refdef.scene.worldmodel)
6707         {
6708                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6709         }
6710         if (r_showsurfaces.integer)
6711         {
6712                 r_refdef.scene.rtworld = false;
6713                 r_refdef.scene.rtworldshadows = false;
6714                 r_refdef.scene.rtdlight = false;
6715                 r_refdef.scene.rtdlightshadows = false;
6716                 r_refdef.lightmapintensity = 0;
6717         }
6718
6719         switch(vid.renderpath)
6720         {
6721         case RENDERPATH_GL20:
6722         case RENDERPATH_D3D9:
6723         case RENDERPATH_D3D10:
6724         case RENDERPATH_D3D11:
6725         case RENDERPATH_SOFT:
6726         case RENDERPATH_GLES2:
6727                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6728                 {
6729                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6730                         {
6731                                 // build GLSL gamma texture
6732 #define RAMPWIDTH 256
6733                                 unsigned short ramp[RAMPWIDTH * 3];
6734                                 unsigned char rampbgr[RAMPWIDTH][4];
6735                                 int i;
6736
6737                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6738
6739                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6740                                 for(i = 0; i < RAMPWIDTH; ++i)
6741                                 {
6742                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6743                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6744                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6745                                         rampbgr[i][3] = 0;
6746                                 }
6747                                 if (r_texture_gammaramps)
6748                                 {
6749                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6750                                 }
6751                                 else
6752                                 {
6753                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6754                                 }
6755                         }
6756                 }
6757                 else
6758                 {
6759                         // remove GLSL gamma texture
6760                 }
6761                 break;
6762         case RENDERPATH_GL11:
6763         case RENDERPATH_GL13:
6764         case RENDERPATH_GLES1:
6765                 break;
6766         }
6767 }
6768
6769 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6770 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6771 /*
6772 ================
6773 R_SelectScene
6774 ================
6775 */
6776 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6777         if( scenetype != r_currentscenetype ) {
6778                 // store the old scenetype
6779                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6780                 r_currentscenetype = scenetype;
6781                 // move in the new scene
6782                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6783         }
6784 }
6785
6786 /*
6787 ================
6788 R_GetScenePointer
6789 ================
6790 */
6791 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6792 {
6793         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6794         if( scenetype == r_currentscenetype ) {
6795                 return &r_refdef.scene;
6796         } else {
6797                 return &r_scenes_store[ scenetype ];
6798         }
6799 }
6800
6801 static int R_SortEntities_Compare(const void *ap, const void *bp)
6802 {
6803         const entity_render_t *a = *(const entity_render_t **)ap;
6804         const entity_render_t *b = *(const entity_render_t **)bp;
6805
6806         // 1. compare model
6807         if(a->model < b->model)
6808                 return -1;
6809         if(a->model > b->model)
6810                 return +1;
6811
6812         // 2. compare skin
6813         // TODO possibly calculate the REAL skinnum here first using
6814         // skinscenes?
6815         if(a->skinnum < b->skinnum)
6816                 return -1;
6817         if(a->skinnum > b->skinnum)
6818                 return +1;
6819
6820         // everything we compared is equal
6821         return 0;
6822 }
6823 static void R_SortEntities(void)
6824 {
6825         // below or equal 2 ents, sorting never gains anything
6826         if(r_refdef.scene.numentities <= 2)
6827                 return;
6828         // sort
6829         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6830 }
6831
6832 /*
6833 ================
6834 R_RenderView
6835 ================
6836 */
6837 int dpsoftrast_test;
6838 extern cvar_t r_shadow_bouncegrid;
6839 void R_RenderView(void)
6840 {
6841         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6842         int fbo;
6843         rtexture_t *depthtexture;
6844         rtexture_t *colortexture;
6845
6846         dpsoftrast_test = r_test.integer;
6847
6848         if (r_timereport_active)
6849                 R_TimeReport("start");
6850         r_textureframe++; // used only by R_GetCurrentTexture
6851         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6852
6853         if(R_CompileShader_CheckStaticParms())
6854                 R_GLSL_Restart_f();
6855
6856         if (!r_drawentities.integer)
6857                 r_refdef.scene.numentities = 0;
6858         else if (r_sortentities.integer)
6859                 R_SortEntities();
6860
6861         R_AnimCache_ClearCache();
6862         R_FrameData_NewFrame();
6863
6864         /* adjust for stereo display */
6865         if(R_Stereo_Active())
6866         {
6867                 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);
6868                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6869         }
6870
6871         if (r_refdef.view.isoverlay)
6872         {
6873                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6874                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6875                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6876                 R_TimeReport("depthclear");
6877
6878                 r_refdef.view.showdebug = false;
6879
6880                 r_fb.water.enabled = false;
6881                 r_fb.water.numwaterplanes = 0;
6882
6883                 R_RenderScene(0, NULL, NULL);
6884
6885                 r_refdef.view.matrix = originalmatrix;
6886
6887                 CHECKGLERROR
6888                 return;
6889         }
6890
6891         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6892         {
6893                 r_refdef.view.matrix = originalmatrix;
6894                 return;
6895         }
6896
6897         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6898
6899         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6900                 // in sRGB fallback, behave similar to true sRGB: convert this
6901                 // value from linear to sRGB
6902                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6903
6904         R_RenderView_UpdateViewVectors();
6905
6906         R_Shadow_UpdateWorldLightSelection();
6907
6908         R_Bloom_StartFrame();
6909         R_Water_StartFrame();
6910
6911         // now we probably have an fbo to render into
6912         fbo = r_fb.fbo;
6913         depthtexture = r_fb.depthtexture;
6914         colortexture = r_fb.colortexture;
6915
6916         CHECKGLERROR
6917         if (r_timereport_active)
6918                 R_TimeReport("viewsetup");
6919
6920         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6921
6922         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6923         {
6924                 R_ClearScreen(r_refdef.fogenabled);
6925                 if (r_timereport_active)
6926                         R_TimeReport("viewclear");
6927         }
6928         r_refdef.view.clear = true;
6929
6930         r_refdef.view.showdebug = true;
6931
6932         R_View_Update();
6933         if (r_timereport_active)
6934                 R_TimeReport("visibility");
6935
6936         R_AnimCache_CacheVisibleEntities();
6937         if (r_timereport_active)
6938                 R_TimeReport("animcache");
6939
6940         R_Shadow_UpdateBounceGridTexture();
6941         if (r_timereport_active && r_shadow_bouncegrid.integer)
6942                 R_TimeReport("bouncegrid");
6943
6944         r_fb.water.numwaterplanes = 0;
6945         if (r_fb.water.enabled)
6946                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6947
6948         R_RenderScene(fbo, depthtexture, colortexture);
6949         r_fb.water.numwaterplanes = 0;
6950
6951         R_BlendView(fbo, depthtexture, colortexture);
6952         if (r_timereport_active)
6953                 R_TimeReport("blendview");
6954
6955         GL_Scissor(0, 0, vid.width, vid.height);
6956         GL_ScissorTest(false);
6957
6958         r_refdef.view.matrix = originalmatrix;
6959
6960         CHECKGLERROR
6961 }
6962
6963 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6964 {
6965         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6966         {
6967                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6968                 if (r_timereport_active)
6969                         R_TimeReport("waterworld");
6970         }
6971
6972         // don't let sound skip if going slow
6973         if (r_refdef.scene.extraupdate)
6974                 S_ExtraUpdate ();
6975
6976         R_DrawModelsAddWaterPlanes();
6977         if (r_timereport_active)
6978                 R_TimeReport("watermodels");
6979
6980         if (r_fb.water.numwaterplanes)
6981         {
6982                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6983                 if (r_timereport_active)
6984                         R_TimeReport("waterscenes");
6985         }
6986 }
6987
6988 extern cvar_t cl_locs_show;
6989 static void R_DrawLocs(void);
6990 static void R_DrawEntityBBoxes(void);
6991 static void R_DrawModelDecals(void);
6992 extern cvar_t cl_decals_newsystem;
6993 extern qboolean r_shadow_usingdeferredprepass;
6994 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6995 {
6996         qboolean shadowmapping = false;
6997
6998         if (r_timereport_active)
6999                 R_TimeReport("beginscene");
7000
7001         r_refdef.stats.renders++;
7002
7003         R_UpdateFog();
7004
7005         // don't let sound skip if going slow
7006         if (r_refdef.scene.extraupdate)
7007                 S_ExtraUpdate ();
7008
7009         R_MeshQueue_BeginScene();
7010
7011         R_SkyStartFrame();
7012
7013         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);
7014
7015         if (r_timereport_active)
7016                 R_TimeReport("skystartframe");
7017
7018         if (cl.csqc_vidvars.drawworld)
7019         {
7020                 // don't let sound skip if going slow
7021                 if (r_refdef.scene.extraupdate)
7022                         S_ExtraUpdate ();
7023
7024                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7025                 {
7026                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7027                         if (r_timereport_active)
7028                                 R_TimeReport("worldsky");
7029                 }
7030
7031                 if (R_DrawBrushModelsSky() && r_timereport_active)
7032                         R_TimeReport("bmodelsky");
7033
7034                 if (skyrendermasked && skyrenderlater)
7035                 {
7036                         // we have to force off the water clipping plane while rendering sky
7037                         R_SetupView(false, fbo, depthtexture, colortexture);
7038                         R_Sky();
7039                         R_SetupView(true, fbo, depthtexture, colortexture);
7040                         if (r_timereport_active)
7041                                 R_TimeReport("sky");
7042                 }
7043         }
7044
7045         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7046         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7047                 R_Shadow_PrepareModelShadows();
7048         if (r_timereport_active)
7049                 R_TimeReport("preparelights");
7050
7051         if (R_Shadow_ShadowMappingEnabled())
7052                 shadowmapping = true;
7053
7054         if (r_shadow_usingdeferredprepass)
7055                 R_Shadow_DrawPrepass();
7056
7057         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7058         {
7059                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7060                 if (r_timereport_active)
7061                         R_TimeReport("worlddepth");
7062         }
7063         if (r_depthfirst.integer >= 2)
7064         {
7065                 R_DrawModelsDepth();
7066                 if (r_timereport_active)
7067                         R_TimeReport("modeldepth");
7068         }
7069
7070         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7071         {
7072                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7073                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7074                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7075                 // don't let sound skip if going slow
7076                 if (r_refdef.scene.extraupdate)
7077                         S_ExtraUpdate ();
7078         }
7079
7080         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7081         {
7082                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7083                 if (r_timereport_active)
7084                         R_TimeReport("world");
7085         }
7086
7087         // don't let sound skip if going slow
7088         if (r_refdef.scene.extraupdate)
7089                 S_ExtraUpdate ();
7090
7091         R_DrawModels();
7092         if (r_timereport_active)
7093                 R_TimeReport("models");
7094
7095         // don't let sound skip if going slow
7096         if (r_refdef.scene.extraupdate)
7097                 S_ExtraUpdate ();
7098
7099         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7100         {
7101                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7102                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7103                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7104                 // don't let sound skip if going slow
7105                 if (r_refdef.scene.extraupdate)
7106                         S_ExtraUpdate ();
7107         }
7108
7109         if (!r_shadow_usingdeferredprepass)
7110         {
7111                 R_Shadow_DrawLights();
7112                 if (r_timereport_active)
7113                         R_TimeReport("rtlights");
7114         }
7115
7116         // don't let sound skip if going slow
7117         if (r_refdef.scene.extraupdate)
7118                 S_ExtraUpdate ();
7119
7120         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7121         {
7122                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7123                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7124                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7125                 // don't let sound skip if going slow
7126                 if (r_refdef.scene.extraupdate)
7127                         S_ExtraUpdate ();
7128         }
7129
7130         if (cl.csqc_vidvars.drawworld)
7131         {
7132                 if (cl_decals_newsystem.integer)
7133                 {
7134                         R_DrawModelDecals();
7135                         if (r_timereport_active)
7136                                 R_TimeReport("modeldecals");
7137                 }
7138                 else
7139                 {
7140                         R_DrawDecals();
7141                         if (r_timereport_active)
7142                                 R_TimeReport("decals");
7143                 }
7144
7145                 R_DrawParticles();
7146                 if (r_timereport_active)
7147                         R_TimeReport("particles");
7148
7149                 R_DrawExplosions();
7150                 if (r_timereport_active)
7151                         R_TimeReport("explosions");
7152
7153                 R_DrawLightningBeams();
7154                 if (r_timereport_active)
7155                         R_TimeReport("lightning");
7156         }
7157
7158         if (cl.csqc_loaded)
7159                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7160
7161         if (r_refdef.view.showdebug)
7162         {
7163                 if (cl_locs_show.integer)
7164                 {
7165                         R_DrawLocs();
7166                         if (r_timereport_active)
7167                                 R_TimeReport("showlocs");
7168                 }
7169
7170                 if (r_drawportals.integer)
7171                 {
7172                         R_DrawPortals();
7173                         if (r_timereport_active)
7174                                 R_TimeReport("portals");
7175                 }
7176
7177                 if (r_showbboxes.value > 0)
7178                 {
7179                         R_DrawEntityBBoxes();
7180                         if (r_timereport_active)
7181                                 R_TimeReport("bboxes");
7182                 }
7183         }
7184
7185         if (r_transparent.integer)
7186         {
7187                 R_MeshQueue_RenderTransparent();
7188                 if (r_timereport_active)
7189                         R_TimeReport("drawtrans");
7190         }
7191
7192         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))
7193         {
7194                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7195                 if (r_timereport_active)
7196                         R_TimeReport("worlddebug");
7197                 R_DrawModelsDebug();
7198                 if (r_timereport_active)
7199                         R_TimeReport("modeldebug");
7200         }
7201
7202         if (cl.csqc_vidvars.drawworld)
7203         {
7204                 R_Shadow_DrawCoronas();
7205                 if (r_timereport_active)
7206                         R_TimeReport("coronas");
7207         }
7208
7209 #if 0
7210         {
7211                 GL_DepthTest(false);
7212                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7213                 GL_Color(1, 1, 1, 1);
7214                 qglBegin(GL_POLYGON);
7215                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7216                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7217                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7218                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7219                 qglEnd();
7220                 qglBegin(GL_POLYGON);
7221                 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]);
7222                 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]);
7223                 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]);
7224                 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]);
7225                 qglEnd();
7226                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7227         }
7228 #endif
7229
7230         // don't let sound skip if going slow
7231         if (r_refdef.scene.extraupdate)
7232                 S_ExtraUpdate ();
7233 }
7234
7235 static const unsigned short bboxelements[36] =
7236 {
7237         5, 1, 3, 5, 3, 7,
7238         6, 2, 0, 6, 0, 4,
7239         7, 3, 2, 7, 2, 6,
7240         4, 0, 1, 4, 1, 5,
7241         4, 5, 7, 4, 7, 6,
7242         1, 0, 2, 1, 2, 3,
7243 };
7244
7245 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7246 {
7247         int i;
7248         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7249
7250         RSurf_ActiveWorldEntity();
7251
7252         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7253         GL_DepthMask(false);
7254         GL_DepthRange(0, 1);
7255         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7256 //      R_Mesh_ResetTextureState();
7257
7258         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7259         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7260         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7261         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7262         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7263         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7264         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7265         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7266         R_FillColors(color4f, 8, cr, cg, cb, ca);
7267         if (r_refdef.fogenabled)
7268         {
7269                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7270                 {
7271                         f1 = RSurf_FogVertex(v);
7272                         f2 = 1 - f1;
7273                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7274                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7275                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7276                 }
7277         }
7278         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7279         R_Mesh_ResetTextureState();
7280         R_SetupShader_Generic_NoTexture(false, false);
7281         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7282 }
7283
7284 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7285 {
7286         prvm_prog_t *prog = SVVM_prog;
7287         int i;
7288         float color[4];
7289         prvm_edict_t *edict;
7290
7291         // this function draws bounding boxes of server entities
7292         if (!sv.active)
7293                 return;
7294
7295         GL_CullFace(GL_NONE);
7296         R_SetupShader_Generic_NoTexture(false, false);
7297
7298         for (i = 0;i < numsurfaces;i++)
7299         {
7300                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7301                 switch ((int)PRVM_serveredictfloat(edict, solid))
7302                 {
7303                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7304                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7305                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7306                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7307                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7308                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7309                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7310                 }
7311                 color[3] *= r_showbboxes.value;
7312                 color[3] = bound(0, color[3], 1);
7313                 GL_DepthTest(!r_showdisabledepthtest.integer);
7314                 GL_CullFace(r_refdef.view.cullface_front);
7315                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7316         }
7317 }
7318
7319 static void R_DrawEntityBBoxes(void)
7320 {
7321         int i;
7322         prvm_edict_t *edict;
7323         vec3_t center;
7324         prvm_prog_t *prog = SVVM_prog;
7325
7326         // this function draws bounding boxes of server entities
7327         if (!sv.active)
7328                 return;
7329
7330         for (i = 0;i < prog->num_edicts;i++)
7331         {
7332                 edict = PRVM_EDICT_NUM(i);
7333                 if (edict->priv.server->free)
7334                         continue;
7335                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7336                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7337                         continue;
7338                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7339                         continue;
7340                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7341                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7342         }
7343 }
7344
7345 static const int nomodelelement3i[24] =
7346 {
7347         5, 2, 0,
7348         5, 1, 2,
7349         5, 0, 3,
7350         5, 3, 1,
7351         0, 2, 4,
7352         2, 1, 4,
7353         3, 0, 4,
7354         1, 3, 4
7355 };
7356
7357 static const unsigned short nomodelelement3s[24] =
7358 {
7359         5, 2, 0,
7360         5, 1, 2,
7361         5, 0, 3,
7362         5, 3, 1,
7363         0, 2, 4,
7364         2, 1, 4,
7365         3, 0, 4,
7366         1, 3, 4
7367 };
7368
7369 static const float nomodelvertex3f[6*3] =
7370 {
7371         -16,   0,   0,
7372          16,   0,   0,
7373           0, -16,   0,
7374           0,  16,   0,
7375           0,   0, -16,
7376           0,   0,  16
7377 };
7378
7379 static const float nomodelcolor4f[6*4] =
7380 {
7381         0.0f, 0.0f, 0.5f, 1.0f,
7382         0.0f, 0.0f, 0.5f, 1.0f,
7383         0.0f, 0.5f, 0.0f, 1.0f,
7384         0.0f, 0.5f, 0.0f, 1.0f,
7385         0.5f, 0.0f, 0.0f, 1.0f,
7386         0.5f, 0.0f, 0.0f, 1.0f
7387 };
7388
7389 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7390 {
7391         int i;
7392         float f1, f2, *c;
7393         float color4f[6*4];
7394
7395         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);
7396
7397         // this is only called once per entity so numsurfaces is always 1, and
7398         // surfacelist is always {0}, so this code does not handle batches
7399
7400         if (rsurface.ent_flags & RENDER_ADDITIVE)
7401         {
7402                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7403                 GL_DepthMask(false);
7404         }
7405         else if (rsurface.colormod[3] < 1)
7406         {
7407                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7408                 GL_DepthMask(false);
7409         }
7410         else
7411         {
7412                 GL_BlendFunc(GL_ONE, GL_ZERO);
7413                 GL_DepthMask(true);
7414         }
7415         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7416         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7417         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7418         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7419         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7420         for (i = 0, c = color4f;i < 6;i++, c += 4)
7421         {
7422                 c[0] *= rsurface.colormod[0];
7423                 c[1] *= rsurface.colormod[1];
7424                 c[2] *= rsurface.colormod[2];
7425                 c[3] *= rsurface.colormod[3];
7426         }
7427         if (r_refdef.fogenabled)
7428         {
7429                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7430                 {
7431                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7432                         f2 = 1 - f1;
7433                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7434                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7435                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7436                 }
7437         }
7438 //      R_Mesh_ResetTextureState();
7439         R_SetupShader_Generic_NoTexture(false, false);
7440         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7441         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7442 }
7443
7444 void R_DrawNoModel(entity_render_t *ent)
7445 {
7446         vec3_t org;
7447         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7448         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7449                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7450         else
7451                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7452 }
7453
7454 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7455 {
7456         vec3_t right1, right2, diff, normal;
7457
7458         VectorSubtract (org2, org1, normal);
7459
7460         // calculate 'right' vector for start
7461         VectorSubtract (r_refdef.view.origin, org1, diff);
7462         CrossProduct (normal, diff, right1);
7463         VectorNormalize (right1);
7464
7465         // calculate 'right' vector for end
7466         VectorSubtract (r_refdef.view.origin, org2, diff);
7467         CrossProduct (normal, diff, right2);
7468         VectorNormalize (right2);
7469
7470         vert[ 0] = org1[0] + width * right1[0];
7471         vert[ 1] = org1[1] + width * right1[1];
7472         vert[ 2] = org1[2] + width * right1[2];
7473         vert[ 3] = org1[0] - width * right1[0];
7474         vert[ 4] = org1[1] - width * right1[1];
7475         vert[ 5] = org1[2] - width * right1[2];
7476         vert[ 6] = org2[0] - width * right2[0];
7477         vert[ 7] = org2[1] - width * right2[1];
7478         vert[ 8] = org2[2] - width * right2[2];
7479         vert[ 9] = org2[0] + width * right2[0];
7480         vert[10] = org2[1] + width * right2[1];
7481         vert[11] = org2[2] + width * right2[2];
7482 }
7483
7484 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)
7485 {
7486         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7487         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7488         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7489         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7490         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7491         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7492         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7493         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7494         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7495         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7496         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7497         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7498 }
7499
7500 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7501 {
7502         int i;
7503         float *vertex3f;
7504         float v[3];
7505         VectorSet(v, x, y, z);
7506         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7507                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7508                         break;
7509         if (i == mesh->numvertices)
7510         {
7511                 if (mesh->numvertices < mesh->maxvertices)
7512                 {
7513                         VectorCopy(v, vertex3f);
7514                         mesh->numvertices++;
7515                 }
7516                 return mesh->numvertices;
7517         }
7518         else
7519                 return i;
7520 }
7521
7522 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7523 {
7524         int i;
7525         int *e, element[3];
7526         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7527         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7528         e = mesh->element3i + mesh->numtriangles * 3;
7529         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7530         {
7531                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7532                 if (mesh->numtriangles < mesh->maxtriangles)
7533                 {
7534                         *e++ = element[0];
7535                         *e++ = element[1];
7536                         *e++ = element[2];
7537                         mesh->numtriangles++;
7538                 }
7539                 element[1] = element[2];
7540         }
7541 }
7542
7543 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7544 {
7545         int i;
7546         int *e, element[3];
7547         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7548         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7549         e = mesh->element3i + mesh->numtriangles * 3;
7550         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7551         {
7552                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7553                 if (mesh->numtriangles < mesh->maxtriangles)
7554                 {
7555                         *e++ = element[0];
7556                         *e++ = element[1];
7557                         *e++ = element[2];
7558                         mesh->numtriangles++;
7559                 }
7560                 element[1] = element[2];
7561         }
7562 }
7563
7564 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7565 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7566 {
7567         int planenum, planenum2;
7568         int w;
7569         int tempnumpoints;
7570         mplane_t *plane, *plane2;
7571         double maxdist;
7572         double temppoints[2][256*3];
7573         // figure out how large a bounding box we need to properly compute this brush
7574         maxdist = 0;
7575         for (w = 0;w < numplanes;w++)
7576                 maxdist = max(maxdist, fabs(planes[w].dist));
7577         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7578         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7579         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7580         {
7581                 w = 0;
7582                 tempnumpoints = 4;
7583                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7584                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7585                 {
7586                         if (planenum2 == planenum)
7587                                 continue;
7588                         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);
7589                         w = !w;
7590                 }
7591                 if (tempnumpoints < 3)
7592                         continue;
7593                 // generate elements forming a triangle fan for this polygon
7594                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7595         }
7596 }
7597
7598 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)
7599 {
7600         texturelayer_t *layer;
7601         layer = t->currentlayers + t->currentnumlayers++;
7602         layer->type = type;
7603         layer->depthmask = depthmask;
7604         layer->blendfunc1 = blendfunc1;
7605         layer->blendfunc2 = blendfunc2;
7606         layer->texture = texture;
7607         layer->texmatrix = *matrix;
7608         layer->color[0] = r;
7609         layer->color[1] = g;
7610         layer->color[2] = b;
7611         layer->color[3] = a;
7612 }
7613
7614 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7615 {
7616         if(parms[0] == 0 && parms[1] == 0)
7617                 return false;
7618         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7619                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7620                         return false;
7621         return true;
7622 }
7623
7624 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7625 {
7626         double index, f;
7627         index = parms[2] + rsurface.shadertime * parms[3];
7628         index -= floor(index);
7629         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7630         {
7631         default:
7632         case Q3WAVEFUNC_NONE:
7633         case Q3WAVEFUNC_NOISE:
7634         case Q3WAVEFUNC_COUNT:
7635                 f = 0;
7636                 break;
7637         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7638         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7639         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7640         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7641         case Q3WAVEFUNC_TRIANGLE:
7642                 index *= 4;
7643                 f = index - floor(index);
7644                 if (index < 1)
7645                 {
7646                         // f = f;
7647                 }
7648                 else if (index < 2)
7649                         f = 1 - f;
7650                 else if (index < 3)
7651                         f = -f;
7652                 else
7653                         f = -(1 - f);
7654                 break;
7655         }
7656         f = parms[0] + parms[1] * f;
7657         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7658                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7659         return (float) f;
7660 }
7661
7662 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7663 {
7664         int w, h, idx;
7665         double f;
7666         double offsetd[2];
7667         float tcmat[12];
7668         matrix4x4_t matrix, temp;
7669         switch(tcmod->tcmod)
7670         {
7671                 case Q3TCMOD_COUNT:
7672                 case Q3TCMOD_NONE:
7673                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7674                                 matrix = r_waterscrollmatrix;
7675                         else
7676                                 matrix = identitymatrix;
7677                         break;
7678                 case Q3TCMOD_ENTITYTRANSLATE:
7679                         // this is used in Q3 to allow the gamecode to control texcoord
7680                         // scrolling on the entity, which is not supported in darkplaces yet.
7681                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7682                         break;
7683                 case Q3TCMOD_ROTATE:
7684                         f = tcmod->parms[0] * rsurface.shadertime;
7685                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7686                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7687                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7688                         break;
7689                 case Q3TCMOD_SCALE:
7690                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7691                         break;
7692                 case Q3TCMOD_SCROLL:
7693                         // extra care is needed because of precision breakdown with large values of time
7694                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7695                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7696                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7697                         break;
7698                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7699                         w = (int) tcmod->parms[0];
7700                         h = (int) tcmod->parms[1];
7701                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7702                         f = f - floor(f);
7703                         idx = (int) floor(f * w * h);
7704                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7705                         break;
7706                 case Q3TCMOD_STRETCH:
7707                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7708                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7709                         break;
7710                 case Q3TCMOD_TRANSFORM:
7711                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7712                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7713                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7714                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7715                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7716                         break;
7717                 case Q3TCMOD_TURBULENT:
7718                         // this is handled in the RSurf_PrepareVertices function
7719                         matrix = identitymatrix;
7720                         break;
7721         }
7722         temp = *texmatrix;
7723         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7724 }
7725
7726 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7727 {
7728         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7729         char name[MAX_QPATH];
7730         skinframe_t *skinframe;
7731         unsigned char pixels[296*194];
7732         strlcpy(cache->name, skinname, sizeof(cache->name));
7733         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7734         if (developer_loading.integer)
7735                 Con_Printf("loading %s\n", name);
7736         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7737         if (!skinframe || !skinframe->base)
7738         {
7739                 unsigned char *f;
7740                 fs_offset_t filesize;
7741                 skinframe = NULL;
7742                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7743                 if (f)
7744                 {
7745                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7746                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7747                         Mem_Free(f);
7748                 }
7749         }
7750         cache->skinframe = skinframe;
7751 }
7752
7753 texture_t *R_GetCurrentTexture(texture_t *t)
7754 {
7755         int i;
7756         const entity_render_t *ent = rsurface.entity;
7757         dp_model_t *model = ent->model;
7758         q3shaderinfo_layer_tcmod_t *tcmod;
7759
7760         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7761                 return t->currentframe;
7762         t->update_lastrenderframe = r_textureframe;
7763         t->update_lastrenderentity = (void *)ent;
7764
7765         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7766                 t->camera_entity = ent->entitynumber;
7767         else
7768                 t->camera_entity = 0;
7769
7770         // switch to an alternate material if this is a q1bsp animated material
7771         {
7772                 texture_t *texture = t;
7773                 int s = rsurface.ent_skinnum;
7774                 if ((unsigned int)s >= (unsigned int)model->numskins)
7775                         s = 0;
7776                 if (model->skinscenes)
7777                 {
7778                         if (model->skinscenes[s].framecount > 1)
7779                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7780                         else
7781                                 s = model->skinscenes[s].firstframe;
7782                 }
7783                 if (s > 0)
7784                         t = t + s * model->num_surfaces;
7785                 if (t->animated)
7786                 {
7787                         // use an alternate animation if the entity's frame is not 0,
7788                         // and only if the texture has an alternate animation
7789                         if (rsurface.ent_alttextures && t->anim_total[1])
7790                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7791                         else
7792                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7793                 }
7794                 texture->currentframe = t;
7795         }
7796
7797         // update currentskinframe to be a qw skin or animation frame
7798         if (rsurface.ent_qwskin >= 0)
7799         {
7800                 i = rsurface.ent_qwskin;
7801                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7802                 {
7803                         r_qwskincache_size = cl.maxclients;
7804                         if (r_qwskincache)
7805                                 Mem_Free(r_qwskincache);
7806                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7807                 }
7808                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7809                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7810                 t->currentskinframe = r_qwskincache[i].skinframe;
7811                 if (t->currentskinframe == NULL)
7812                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7813         }
7814         else if (t->numskinframes >= 2)
7815                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7816         if (t->backgroundnumskinframes >= 2)
7817                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7818
7819         t->currentmaterialflags = t->basematerialflags;
7820         t->currentalpha = rsurface.colormod[3];
7821         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7822                 t->currentalpha *= r_wateralpha.value;
7823         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7824                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7825         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7826                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7827         if (!(rsurface.ent_flags & RENDER_LIGHT))
7828                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7829         else if (FAKELIGHT_ENABLED)
7830         {
7831                 // no modellight if using fakelight for the map
7832         }
7833         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7834         {
7835                 // pick a model lighting mode
7836                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7837                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7838                 else
7839                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7840         }
7841         if (rsurface.ent_flags & RENDER_ADDITIVE)
7842                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7843         else if (t->currentalpha < 1)
7844                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7845         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7846         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7847                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7848         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7849                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7850         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7851                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7852         if (t->backgroundnumskinframes)
7853                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7854         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7855         {
7856                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7857                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7858         }
7859         else
7860                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7861         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7862         {
7863                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7864                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7865         }
7866         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7867                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7868
7869         // there is no tcmod
7870         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7871         {
7872                 t->currenttexmatrix = r_waterscrollmatrix;
7873                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7874         }
7875         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7876         {
7877                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7878                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7879         }
7880
7881         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7882                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7883         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7884                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7885
7886         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7887         if (t->currentskinframe->qpixels)
7888                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7889         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7890         if (!t->basetexture)
7891                 t->basetexture = r_texture_notexture;
7892         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7893         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7894         t->nmaptexture = t->currentskinframe->nmap;
7895         if (!t->nmaptexture)
7896                 t->nmaptexture = r_texture_blanknormalmap;
7897         t->glosstexture = r_texture_black;
7898         t->glowtexture = t->currentskinframe->glow;
7899         t->fogtexture = t->currentskinframe->fog;
7900         t->reflectmasktexture = t->currentskinframe->reflect;
7901         if (t->backgroundnumskinframes)
7902         {
7903                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7904                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7905                 t->backgroundglosstexture = r_texture_black;
7906                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7907                 if (!t->backgroundnmaptexture)
7908                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7909                 // make sure that if glow is going to be used, both textures are not NULL
7910                 if (!t->backgroundglowtexture && t->glowtexture)
7911                         t->backgroundglowtexture = r_texture_black;
7912                 if (!t->glowtexture && t->backgroundglowtexture)
7913                         t->glowtexture = r_texture_black;
7914         }
7915         else
7916         {
7917                 t->backgroundbasetexture = r_texture_white;
7918                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7919                 t->backgroundglosstexture = r_texture_black;
7920                 t->backgroundglowtexture = NULL;
7921         }
7922         t->specularpower = r_shadow_glossexponent.value;
7923         // TODO: store reference values for these in the texture?
7924         t->specularscale = 0;
7925         if (r_shadow_gloss.integer > 0)
7926         {
7927                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7928                 {
7929                         if (r_shadow_glossintensity.value > 0)
7930                         {
7931                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7932                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7933                                 t->specularscale = r_shadow_glossintensity.value;
7934                         }
7935                 }
7936                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7937                 {
7938                         t->glosstexture = r_texture_white;
7939                         t->backgroundglosstexture = r_texture_white;
7940                         t->specularscale = r_shadow_gloss2intensity.value;
7941                         t->specularpower = r_shadow_gloss2exponent.value;
7942                 }
7943         }
7944         t->specularscale *= t->specularscalemod;
7945         t->specularpower *= t->specularpowermod;
7946         t->rtlightambient = 0;
7947
7948         // lightmaps mode looks bad with dlights using actual texturing, so turn
7949         // off the colormap and glossmap, but leave the normalmap on as it still
7950         // accurately represents the shading involved
7951         if (gl_lightmaps.integer)
7952         {
7953                 t->basetexture = r_texture_grey128;
7954                 t->pantstexture = r_texture_black;
7955                 t->shirttexture = r_texture_black;
7956                 t->nmaptexture = r_texture_blanknormalmap;
7957                 t->glosstexture = r_texture_black;
7958                 t->glowtexture = NULL;
7959                 t->fogtexture = NULL;
7960                 t->reflectmasktexture = NULL;
7961                 t->backgroundbasetexture = NULL;
7962                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7963                 t->backgroundglosstexture = r_texture_black;
7964                 t->backgroundglowtexture = NULL;
7965                 t->specularscale = 0;
7966                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7967         }
7968
7969         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7970         VectorClear(t->dlightcolor);
7971         t->currentnumlayers = 0;
7972         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7973         {
7974                 int blendfunc1, blendfunc2;
7975                 qboolean depthmask;
7976                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7977                 {
7978                         blendfunc1 = GL_SRC_ALPHA;
7979                         blendfunc2 = GL_ONE;
7980                 }
7981                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7982                 {
7983                         blendfunc1 = GL_SRC_ALPHA;
7984                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7985                 }
7986                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7987                 {
7988                         blendfunc1 = t->customblendfunc[0];
7989                         blendfunc2 = t->customblendfunc[1];
7990                 }
7991                 else
7992                 {
7993                         blendfunc1 = GL_ONE;
7994                         blendfunc2 = GL_ZERO;
7995                 }
7996                 // don't colormod evilblend textures
7997                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
7998                         VectorSet(t->lightmapcolor, 1, 1, 1);
7999                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8000                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8001                 {
8002                         // fullbright is not affected by r_refdef.lightmapintensity
8003                         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]);
8004                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8005                                 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]);
8006                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8007                                 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]);
8008                 }
8009                 else
8010                 {
8011                         vec3_t ambientcolor;
8012                         float colorscale;
8013                         // set the color tint used for lights affecting this surface
8014                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8015                         colorscale = 2;
8016                         // q3bsp has no lightmap updates, so the lightstylevalue that
8017                         // would normally be baked into the lightmap must be
8018                         // applied to the color
8019                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8020                         if (model->type == mod_brushq3)
8021                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8022                         colorscale *= r_refdef.lightmapintensity;
8023                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8024                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8025                         // basic lit geometry
8026                         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]);
8027                         // add pants/shirt if needed
8028                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8029                                 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]);
8030                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8031                                 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]);
8032                         // now add ambient passes if needed
8033                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8034                         {
8035                                 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]);
8036                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8037                                         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]);
8038                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8039                                         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]);
8040                         }
8041                 }
8042                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8043                         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]);
8044                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8045                 {
8046                         // if this is opaque use alpha blend which will darken the earlier
8047                         // passes cheaply.
8048                         //
8049                         // if this is an alpha blended material, all the earlier passes
8050                         // were darkened by fog already, so we only need to add the fog
8051                         // color ontop through the fog mask texture
8052                         //
8053                         // if this is an additive blended material, all the earlier passes
8054                         // were darkened by fog already, and we should not add fog color
8055                         // (because the background was not darkened, there is no fog color
8056                         // that was lost behind it).
8057                         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]);
8058                 }
8059         }
8060
8061         return t->currentframe;
8062 }
8063
8064 rsurfacestate_t rsurface;
8065
8066 void RSurf_ActiveWorldEntity(void)
8067 {
8068         dp_model_t *model = r_refdef.scene.worldmodel;
8069         //if (rsurface.entity == r_refdef.scene.worldentity)
8070         //      return;
8071         rsurface.entity = r_refdef.scene.worldentity;
8072         rsurface.skeleton = NULL;
8073         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8074         rsurface.ent_skinnum = 0;
8075         rsurface.ent_qwskin = -1;
8076         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8077         rsurface.shadertime = r_refdef.scene.time;
8078         rsurface.matrix = identitymatrix;
8079         rsurface.inversematrix = identitymatrix;
8080         rsurface.matrixscale = 1;
8081         rsurface.inversematrixscale = 1;
8082         R_EntityMatrix(&identitymatrix);
8083         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8084         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8085         rsurface.fograngerecip = r_refdef.fograngerecip;
8086         rsurface.fogheightfade = r_refdef.fogheightfade;
8087         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8088         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8089         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8090         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8091         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8092         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8093         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8094         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8095         rsurface.colormod[3] = 1;
8096         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);
8097         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8098         rsurface.frameblend[0].lerp = 1;
8099         rsurface.ent_alttextures = false;
8100         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8101         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8102         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8103         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8104         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8105         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8106         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8107         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8108         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8109         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8110         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8111         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8112         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8113         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8114         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8115         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8116         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8117         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8118         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8119         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8120         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8121         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8122         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8123         rsurface.modelelement3i = model->surfmesh.data_element3i;
8124         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8125         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8126         rsurface.modelelement3s = model->surfmesh.data_element3s;
8127         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8128         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8129         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8130         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8131         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8132         rsurface.modelsurfaces = model->data_surfaces;
8133         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8134         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8135         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8136         rsurface.modelgeneratedvertex = false;
8137         rsurface.batchgeneratedvertex = false;
8138         rsurface.batchfirstvertex = 0;
8139         rsurface.batchnumvertices = 0;
8140         rsurface.batchfirsttriangle = 0;
8141         rsurface.batchnumtriangles = 0;
8142         rsurface.batchvertex3f  = NULL;
8143         rsurface.batchvertex3f_vertexbuffer = NULL;
8144         rsurface.batchvertex3f_bufferoffset = 0;
8145         rsurface.batchsvector3f = NULL;
8146         rsurface.batchsvector3f_vertexbuffer = NULL;
8147         rsurface.batchsvector3f_bufferoffset = 0;
8148         rsurface.batchtvector3f = NULL;
8149         rsurface.batchtvector3f_vertexbuffer = NULL;
8150         rsurface.batchtvector3f_bufferoffset = 0;
8151         rsurface.batchnormal3f  = NULL;
8152         rsurface.batchnormal3f_vertexbuffer = NULL;
8153         rsurface.batchnormal3f_bufferoffset = 0;
8154         rsurface.batchlightmapcolor4f = NULL;
8155         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8156         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8157         rsurface.batchtexcoordtexture2f = NULL;
8158         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8159         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8160         rsurface.batchtexcoordlightmap2f = NULL;
8161         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8162         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8163         rsurface.batchvertexmesh = NULL;
8164         rsurface.batchvertexmeshbuffer = NULL;
8165         rsurface.batchvertex3fbuffer = NULL;
8166         rsurface.batchelement3i = NULL;
8167         rsurface.batchelement3i_indexbuffer = NULL;
8168         rsurface.batchelement3i_bufferoffset = 0;
8169         rsurface.batchelement3s = NULL;
8170         rsurface.batchelement3s_indexbuffer = NULL;
8171         rsurface.batchelement3s_bufferoffset = 0;
8172         rsurface.passcolor4f = NULL;
8173         rsurface.passcolor4f_vertexbuffer = NULL;
8174         rsurface.passcolor4f_bufferoffset = 0;
8175         rsurface.forcecurrenttextureupdate = false;
8176 }
8177
8178 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8179 {
8180         dp_model_t *model = ent->model;
8181         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8182         //      return;
8183         rsurface.entity = (entity_render_t *)ent;
8184         rsurface.skeleton = ent->skeleton;
8185         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8186         rsurface.ent_skinnum = ent->skinnum;
8187         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;
8188         rsurface.ent_flags = ent->flags;
8189         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8190         rsurface.matrix = ent->matrix;
8191         rsurface.inversematrix = ent->inversematrix;
8192         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8193         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8194         R_EntityMatrix(&rsurface.matrix);
8195         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8196         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8197         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8198         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8199         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8200         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8201         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8202         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8203         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8204         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8205         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8206         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8207         rsurface.colormod[3] = ent->alpha;
8208         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8209         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8210         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8211         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8212         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8213         if (ent->model->brush.submodel && !prepass)
8214         {
8215                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8216                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8217         }
8218         if (model->surfmesh.isanimated && model->AnimateVertices)
8219         {
8220                 if (ent->animcache_vertex3f)
8221                 {
8222                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8223                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8224                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8225                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8226                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8227                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8228                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8229                 }
8230                 else if (wanttangents)
8231                 {
8232                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8233                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8234                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8235                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8236                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8237                         rsurface.modelvertexmesh = NULL;
8238                         rsurface.modelvertexmeshbuffer = NULL;
8239                         rsurface.modelvertex3fbuffer = NULL;
8240                 }
8241                 else if (wantnormals)
8242                 {
8243                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8244                         rsurface.modelsvector3f = NULL;
8245                         rsurface.modeltvector3f = NULL;
8246                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8247                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8248                         rsurface.modelvertexmesh = NULL;
8249                         rsurface.modelvertexmeshbuffer = NULL;
8250                         rsurface.modelvertex3fbuffer = NULL;
8251                 }
8252                 else
8253                 {
8254                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8255                         rsurface.modelsvector3f = NULL;
8256                         rsurface.modeltvector3f = NULL;
8257                         rsurface.modelnormal3f = NULL;
8258                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8259                         rsurface.modelvertexmesh = NULL;
8260                         rsurface.modelvertexmeshbuffer = NULL;
8261                         rsurface.modelvertex3fbuffer = NULL;
8262                 }
8263                 rsurface.modelvertex3f_vertexbuffer = 0;
8264                 rsurface.modelvertex3f_bufferoffset = 0;
8265                 rsurface.modelsvector3f_vertexbuffer = 0;
8266                 rsurface.modelsvector3f_bufferoffset = 0;
8267                 rsurface.modeltvector3f_vertexbuffer = 0;
8268                 rsurface.modeltvector3f_bufferoffset = 0;
8269                 rsurface.modelnormal3f_vertexbuffer = 0;
8270                 rsurface.modelnormal3f_bufferoffset = 0;
8271                 rsurface.modelgeneratedvertex = true;
8272         }
8273         else
8274         {
8275                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8276                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8277                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8278                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8279                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8280                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8281                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8282                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8283                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8284                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8285                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8286                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8287                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8288                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8289                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8290                 rsurface.modelgeneratedvertex = false;
8291         }
8292         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8293         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8294         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8295         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8296         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8297         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8298         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8299         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8300         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8301         rsurface.modelelement3i = model->surfmesh.data_element3i;
8302         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8303         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8304         rsurface.modelelement3s = model->surfmesh.data_element3s;
8305         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8306         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8307         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8308         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8309         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8310         rsurface.modelsurfaces = model->data_surfaces;
8311         rsurface.batchgeneratedvertex = false;
8312         rsurface.batchfirstvertex = 0;
8313         rsurface.batchnumvertices = 0;
8314         rsurface.batchfirsttriangle = 0;
8315         rsurface.batchnumtriangles = 0;
8316         rsurface.batchvertex3f  = NULL;
8317         rsurface.batchvertex3f_vertexbuffer = NULL;
8318         rsurface.batchvertex3f_bufferoffset = 0;
8319         rsurface.batchsvector3f = NULL;
8320         rsurface.batchsvector3f_vertexbuffer = NULL;
8321         rsurface.batchsvector3f_bufferoffset = 0;
8322         rsurface.batchtvector3f = NULL;
8323         rsurface.batchtvector3f_vertexbuffer = NULL;
8324         rsurface.batchtvector3f_bufferoffset = 0;
8325         rsurface.batchnormal3f  = NULL;
8326         rsurface.batchnormal3f_vertexbuffer = NULL;
8327         rsurface.batchnormal3f_bufferoffset = 0;
8328         rsurface.batchlightmapcolor4f = NULL;
8329         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8330         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8331         rsurface.batchtexcoordtexture2f = NULL;
8332         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8333         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8334         rsurface.batchtexcoordlightmap2f = NULL;
8335         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8336         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8337         rsurface.batchvertexmesh = NULL;
8338         rsurface.batchvertexmeshbuffer = NULL;
8339         rsurface.batchvertex3fbuffer = NULL;
8340         rsurface.batchelement3i = NULL;
8341         rsurface.batchelement3i_indexbuffer = NULL;
8342         rsurface.batchelement3i_bufferoffset = 0;
8343         rsurface.batchelement3s = NULL;
8344         rsurface.batchelement3s_indexbuffer = NULL;
8345         rsurface.batchelement3s_bufferoffset = 0;
8346         rsurface.passcolor4f = NULL;
8347         rsurface.passcolor4f_vertexbuffer = NULL;
8348         rsurface.passcolor4f_bufferoffset = 0;
8349         rsurface.forcecurrenttextureupdate = false;
8350 }
8351
8352 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)
8353 {
8354         rsurface.entity = r_refdef.scene.worldentity;
8355         rsurface.skeleton = NULL;
8356         rsurface.ent_skinnum = 0;
8357         rsurface.ent_qwskin = -1;
8358         rsurface.ent_flags = entflags;
8359         rsurface.shadertime = r_refdef.scene.time - shadertime;
8360         rsurface.modelnumvertices = numvertices;
8361         rsurface.modelnumtriangles = numtriangles;
8362         rsurface.matrix = *matrix;
8363         rsurface.inversematrix = *inversematrix;
8364         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8365         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8366         R_EntityMatrix(&rsurface.matrix);
8367         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8368         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8369         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8370         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8371         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8372         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8373         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8374         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8375         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8376         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8377         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8378         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8379         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);
8380         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8381         rsurface.frameblend[0].lerp = 1;
8382         rsurface.ent_alttextures = false;
8383         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8384         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8385         if (wanttangents)
8386         {
8387                 rsurface.modelvertex3f = (float *)vertex3f;
8388                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8389                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8390                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8391         }
8392         else if (wantnormals)
8393         {
8394                 rsurface.modelvertex3f = (float *)vertex3f;
8395                 rsurface.modelsvector3f = NULL;
8396                 rsurface.modeltvector3f = NULL;
8397                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8398         }
8399         else
8400         {
8401                 rsurface.modelvertex3f = (float *)vertex3f;
8402                 rsurface.modelsvector3f = NULL;
8403                 rsurface.modeltvector3f = NULL;
8404                 rsurface.modelnormal3f = NULL;
8405         }
8406         rsurface.modelvertexmesh = NULL;
8407         rsurface.modelvertexmeshbuffer = NULL;
8408         rsurface.modelvertex3fbuffer = NULL;
8409         rsurface.modelvertex3f_vertexbuffer = 0;
8410         rsurface.modelvertex3f_bufferoffset = 0;
8411         rsurface.modelsvector3f_vertexbuffer = 0;
8412         rsurface.modelsvector3f_bufferoffset = 0;
8413         rsurface.modeltvector3f_vertexbuffer = 0;
8414         rsurface.modeltvector3f_bufferoffset = 0;
8415         rsurface.modelnormal3f_vertexbuffer = 0;
8416         rsurface.modelnormal3f_bufferoffset = 0;
8417         rsurface.modelgeneratedvertex = true;
8418         rsurface.modellightmapcolor4f  = (float *)color4f;
8419         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8420         rsurface.modellightmapcolor4f_bufferoffset = 0;
8421         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8422         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8423         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8424         rsurface.modeltexcoordlightmap2f  = NULL;
8425         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8426         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8427         rsurface.modelelement3i = (int *)element3i;
8428         rsurface.modelelement3i_indexbuffer = NULL;
8429         rsurface.modelelement3i_bufferoffset = 0;
8430         rsurface.modelelement3s = (unsigned short *)element3s;
8431         rsurface.modelelement3s_indexbuffer = NULL;
8432         rsurface.modelelement3s_bufferoffset = 0;
8433         rsurface.modellightmapoffsets = NULL;
8434         rsurface.modelsurfaces = NULL;
8435         rsurface.batchgeneratedvertex = false;
8436         rsurface.batchfirstvertex = 0;
8437         rsurface.batchnumvertices = 0;
8438         rsurface.batchfirsttriangle = 0;
8439         rsurface.batchnumtriangles = 0;
8440         rsurface.batchvertex3f  = NULL;
8441         rsurface.batchvertex3f_vertexbuffer = NULL;
8442         rsurface.batchvertex3f_bufferoffset = 0;
8443         rsurface.batchsvector3f = NULL;
8444         rsurface.batchsvector3f_vertexbuffer = NULL;
8445         rsurface.batchsvector3f_bufferoffset = 0;
8446         rsurface.batchtvector3f = NULL;
8447         rsurface.batchtvector3f_vertexbuffer = NULL;
8448         rsurface.batchtvector3f_bufferoffset = 0;
8449         rsurface.batchnormal3f  = NULL;
8450         rsurface.batchnormal3f_vertexbuffer = NULL;
8451         rsurface.batchnormal3f_bufferoffset = 0;
8452         rsurface.batchlightmapcolor4f = NULL;
8453         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8454         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8455         rsurface.batchtexcoordtexture2f = NULL;
8456         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8457         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8458         rsurface.batchtexcoordlightmap2f = NULL;
8459         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8460         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8461         rsurface.batchvertexmesh = NULL;
8462         rsurface.batchvertexmeshbuffer = NULL;
8463         rsurface.batchvertex3fbuffer = NULL;
8464         rsurface.batchelement3i = NULL;
8465         rsurface.batchelement3i_indexbuffer = NULL;
8466         rsurface.batchelement3i_bufferoffset = 0;
8467         rsurface.batchelement3s = NULL;
8468         rsurface.batchelement3s_indexbuffer = NULL;
8469         rsurface.batchelement3s_bufferoffset = 0;
8470         rsurface.passcolor4f = NULL;
8471         rsurface.passcolor4f_vertexbuffer = NULL;
8472         rsurface.passcolor4f_bufferoffset = 0;
8473         rsurface.forcecurrenttextureupdate = true;
8474
8475         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8476         {
8477                 if ((wantnormals || wanttangents) && !normal3f)
8478                 {
8479                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8480                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8481                 }
8482                 if (wanttangents && !svector3f)
8483                 {
8484                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8485                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8486                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8487                 }
8488         }
8489 }
8490
8491 float RSurf_FogPoint(const float *v)
8492 {
8493         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8494         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8495         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8496         float FogHeightFade = r_refdef.fogheightfade;
8497         float fogfrac;
8498         unsigned int fogmasktableindex;
8499         if (r_refdef.fogplaneviewabove)
8500                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8501         else
8502                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8503         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8504         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8505 }
8506
8507 float RSurf_FogVertex(const float *v)
8508 {
8509         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8510         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8511         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8512         float FogHeightFade = rsurface.fogheightfade;
8513         float fogfrac;
8514         unsigned int fogmasktableindex;
8515         if (r_refdef.fogplaneviewabove)
8516                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8517         else
8518                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8519         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8520         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8521 }
8522
8523 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8524 {
8525         int i;
8526         for (i = 0;i < numelements;i++)
8527                 outelement3i[i] = inelement3i[i] + adjust;
8528 }
8529
8530 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8531 extern cvar_t gl_vbo;
8532 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8533 {
8534         int deformindex;
8535         int firsttriangle;
8536         int numtriangles;
8537         int firstvertex;
8538         int endvertex;
8539         int numvertices;
8540         int surfacefirsttriangle;
8541         int surfacenumtriangles;
8542         int surfacefirstvertex;
8543         int surfaceendvertex;
8544         int surfacenumvertices;
8545         int batchnumvertices;
8546         int batchnumtriangles;
8547         int needsupdate;
8548         int i, j;
8549         qboolean gaps;
8550         qboolean dynamicvertex;
8551         float amplitude;
8552         float animpos;
8553         float scale;
8554         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8555         float waveparms[4];
8556         q3shaderinfo_deform_t *deform;
8557         const msurface_t *surface, *firstsurface;
8558         r_vertexmesh_t *vertexmesh;
8559         if (!texturenumsurfaces)
8560                 return;
8561         // find vertex range of this surface batch
8562         gaps = false;
8563         firstsurface = texturesurfacelist[0];
8564         firsttriangle = firstsurface->num_firsttriangle;
8565         batchnumvertices = 0;
8566         batchnumtriangles = 0;
8567         firstvertex = endvertex = firstsurface->num_firstvertex;
8568         for (i = 0;i < texturenumsurfaces;i++)
8569         {
8570                 surface = texturesurfacelist[i];
8571                 if (surface != firstsurface + i)
8572                         gaps = true;
8573                 surfacefirstvertex = surface->num_firstvertex;
8574                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8575                 surfacenumvertices = surface->num_vertices;
8576                 surfacenumtriangles = surface->num_triangles;
8577                 if (firstvertex > surfacefirstvertex)
8578                         firstvertex = surfacefirstvertex;
8579                 if (endvertex < surfaceendvertex)
8580                         endvertex = surfaceendvertex;
8581                 batchnumvertices += surfacenumvertices;
8582                 batchnumtriangles += surfacenumtriangles;
8583         }
8584
8585         // we now know the vertex range used, and if there are any gaps in it
8586         rsurface.batchfirstvertex = firstvertex;
8587         rsurface.batchnumvertices = endvertex - firstvertex;
8588         rsurface.batchfirsttriangle = firsttriangle;
8589         rsurface.batchnumtriangles = batchnumtriangles;
8590
8591         // this variable holds flags for which properties have been updated that
8592         // may require regenerating vertexmesh array...
8593         needsupdate = 0;
8594
8595         // check if any dynamic vertex processing must occur
8596         dynamicvertex = false;
8597
8598         // if there is a chance of animated vertex colors, it's a dynamic batch
8599         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8600         {
8601                 dynamicvertex = true;
8602                 batchneed |= BATCHNEED_NOGAPS;
8603                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8604         }
8605
8606         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8607         {
8608                 switch (deform->deform)
8609                 {
8610                 default:
8611                 case Q3DEFORM_PROJECTIONSHADOW:
8612                 case Q3DEFORM_TEXT0:
8613                 case Q3DEFORM_TEXT1:
8614                 case Q3DEFORM_TEXT2:
8615                 case Q3DEFORM_TEXT3:
8616                 case Q3DEFORM_TEXT4:
8617                 case Q3DEFORM_TEXT5:
8618                 case Q3DEFORM_TEXT6:
8619                 case Q3DEFORM_TEXT7:
8620                 case Q3DEFORM_NONE:
8621                         break;
8622                 case Q3DEFORM_AUTOSPRITE:
8623                         dynamicvertex = true;
8624                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8625                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8626                         break;
8627                 case Q3DEFORM_AUTOSPRITE2:
8628                         dynamicvertex = true;
8629                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8630                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8631                         break;
8632                 case Q3DEFORM_NORMAL:
8633                         dynamicvertex = true;
8634                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8635                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8636                         break;
8637                 case Q3DEFORM_WAVE:
8638                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8639                                 break; // if wavefunc is a nop, ignore this transform
8640                         dynamicvertex = true;
8641                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8642                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8643                         break;
8644                 case Q3DEFORM_BULGE:
8645                         dynamicvertex = true;
8646                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8647                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8648                         break;
8649                 case Q3DEFORM_MOVE:
8650                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8651                                 break; // if wavefunc is a nop, ignore this transform
8652                         dynamicvertex = true;
8653                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8654                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8655                         break;
8656                 }
8657         }
8658         switch(rsurface.texture->tcgen.tcgen)
8659         {
8660         default:
8661         case Q3TCGEN_TEXTURE:
8662                 break;
8663         case Q3TCGEN_LIGHTMAP:
8664                 dynamicvertex = true;
8665                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8666                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8667                 break;
8668         case Q3TCGEN_VECTOR:
8669                 dynamicvertex = true;
8670                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8671                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8672                 break;
8673         case Q3TCGEN_ENVIRONMENT:
8674                 dynamicvertex = true;
8675                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8676                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8677                 break;
8678         }
8679         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8680         {
8681                 dynamicvertex = true;
8682                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8683                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8684         }
8685
8686         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8687         {
8688                 dynamicvertex = true;
8689                 batchneed |= BATCHNEED_NOGAPS;
8690                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8691         }
8692
8693         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8694         {
8695                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8696                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8697                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8698                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8699                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8700                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8701                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8702         }
8703
8704         // when the model data has no vertex buffer (dynamic mesh), we need to
8705         // eliminate gaps
8706         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8707                 batchneed |= BATCHNEED_NOGAPS;
8708
8709         // if needsupdate, we have to do a dynamic vertex batch for sure
8710         if (needsupdate & batchneed)
8711                 dynamicvertex = true;
8712
8713         // see if we need to build vertexmesh from arrays
8714         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8715                 dynamicvertex = true;
8716
8717         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8718         // also some drivers strongly dislike firstvertex
8719         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8720                 dynamicvertex = true;
8721
8722         rsurface.batchvertex3f = rsurface.modelvertex3f;
8723         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8724         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8725         rsurface.batchsvector3f = rsurface.modelsvector3f;
8726         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8727         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8728         rsurface.batchtvector3f = rsurface.modeltvector3f;
8729         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8730         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8731         rsurface.batchnormal3f = rsurface.modelnormal3f;
8732         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8733         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8734         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8735         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8736         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8737         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8738         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8739         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8740         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8741         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8742         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8743         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8744         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8745         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8746         rsurface.batchelement3i = rsurface.modelelement3i;
8747         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8748         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8749         rsurface.batchelement3s = rsurface.modelelement3s;
8750         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8751         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8752
8753         // if any dynamic vertex processing has to occur in software, we copy the
8754         // entire surface list together before processing to rebase the vertices
8755         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8756         //
8757         // if any gaps exist and we do not have a static vertex buffer, we have to
8758         // copy the surface list together to avoid wasting upload bandwidth on the
8759         // vertices in the gaps.
8760         //
8761         // if gaps exist and we have a static vertex buffer, we still have to
8762         // combine the index buffer ranges into one dynamic index buffer.
8763         //
8764         // in all cases we end up with data that can be drawn in one call.
8765
8766         if (!dynamicvertex)
8767         {
8768                 // static vertex data, just set pointers...
8769                 rsurface.batchgeneratedvertex = false;
8770                 // if there are gaps, we want to build a combined index buffer,
8771                 // otherwise use the original static buffer with an appropriate offset
8772                 if (gaps)
8773                 {
8774                         // build a new triangle elements array for this batch
8775                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8776                         rsurface.batchfirsttriangle = 0;
8777                         numtriangles = 0;
8778                         for (i = 0;i < texturenumsurfaces;i++)
8779                         {
8780                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8781                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8782                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8783                                 numtriangles += surfacenumtriangles;
8784                         }
8785                         rsurface.batchelement3i_indexbuffer = NULL;
8786                         rsurface.batchelement3i_bufferoffset = 0;
8787                         rsurface.batchelement3s = NULL;
8788                         rsurface.batchelement3s_indexbuffer = NULL;
8789                         rsurface.batchelement3s_bufferoffset = 0;
8790                         if (endvertex <= 65536)
8791                         {
8792                                 // make a 16bit (unsigned short) index array if possible
8793                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8794                                 for (i = 0;i < numtriangles*3;i++)
8795                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8796                         }
8797                 }
8798                 return;
8799         }
8800
8801         // something needs software processing, do it for real...
8802         // we only directly handle separate array data in this case and then
8803         // generate interleaved data if needed...
8804         rsurface.batchgeneratedvertex = true;
8805
8806         // now copy the vertex data into a combined array and make an index array
8807         // (this is what Quake3 does all the time)
8808         //if (gaps || rsurface.batchfirstvertex)
8809         {
8810                 rsurface.batchvertex3fbuffer = NULL;
8811                 rsurface.batchvertexmesh = NULL;
8812                 rsurface.batchvertexmeshbuffer = NULL;
8813                 rsurface.batchvertex3f = NULL;
8814                 rsurface.batchvertex3f_vertexbuffer = NULL;
8815                 rsurface.batchvertex3f_bufferoffset = 0;
8816                 rsurface.batchsvector3f = NULL;
8817                 rsurface.batchsvector3f_vertexbuffer = NULL;
8818                 rsurface.batchsvector3f_bufferoffset = 0;
8819                 rsurface.batchtvector3f = NULL;
8820                 rsurface.batchtvector3f_vertexbuffer = NULL;
8821                 rsurface.batchtvector3f_bufferoffset = 0;
8822                 rsurface.batchnormal3f = NULL;
8823                 rsurface.batchnormal3f_vertexbuffer = NULL;
8824                 rsurface.batchnormal3f_bufferoffset = 0;
8825                 rsurface.batchlightmapcolor4f = NULL;
8826                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8827                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8828                 rsurface.batchtexcoordtexture2f = NULL;
8829                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8830                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8831                 rsurface.batchtexcoordlightmap2f = NULL;
8832                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8833                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8834                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8835                 rsurface.batchelement3i_indexbuffer = NULL;
8836                 rsurface.batchelement3i_bufferoffset = 0;
8837                 rsurface.batchelement3s = NULL;
8838                 rsurface.batchelement3s_indexbuffer = NULL;
8839                 rsurface.batchelement3s_bufferoffset = 0;
8840                 // we'll only be setting up certain arrays as needed
8841                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8842                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8843                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8844                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8845                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8846                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8847                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8848                 {
8849                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8850                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8851                 }
8852                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8853                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8854                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8855                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8856                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8857                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8858                 numvertices = 0;
8859                 numtriangles = 0;
8860                 for (i = 0;i < texturenumsurfaces;i++)
8861                 {
8862                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8863                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8864                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8865                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8866                         // copy only the data requested
8867                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8868                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8869                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8870                         {
8871                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8872                                 {
8873                                         if (rsurface.batchvertex3f)
8874                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8875                                         else
8876                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8877                                 }
8878                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8879                                 {
8880                                         if (rsurface.modelnormal3f)
8881                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8882                                         else
8883                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8884                                 }
8885                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8886                                 {
8887                                         if (rsurface.modelsvector3f)
8888                                         {
8889                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8890                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8891                                         }
8892                                         else
8893                                         {
8894                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8895                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8896                                         }
8897                                 }
8898                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8899                                 {
8900                                         if (rsurface.modellightmapcolor4f)
8901                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8902                                         else
8903                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8904                                 }
8905                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8906                                 {
8907                                         if (rsurface.modeltexcoordtexture2f)
8908                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8909                                         else
8910                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8911                                 }
8912                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8913                                 {
8914                                         if (rsurface.modeltexcoordlightmap2f)
8915                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8916                                         else
8917                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8918                                 }
8919                         }
8920                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8921                         numvertices += surfacenumvertices;
8922                         numtriangles += surfacenumtriangles;
8923                 }
8924
8925                 // generate a 16bit index array as well if possible
8926                 // (in general, dynamic batches fit)
8927                 if (numvertices <= 65536)
8928                 {
8929                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8930                         for (i = 0;i < numtriangles*3;i++)
8931                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8932                 }
8933
8934                 // since we've copied everything, the batch now starts at 0
8935                 rsurface.batchfirstvertex = 0;
8936                 rsurface.batchnumvertices = batchnumvertices;
8937                 rsurface.batchfirsttriangle = 0;
8938                 rsurface.batchnumtriangles = batchnumtriangles;
8939         }
8940
8941         // q1bsp surfaces rendered in vertex color mode have to have colors
8942         // calculated based on lightstyles
8943         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8944         {
8945                 // generate color arrays for the surfaces in this list
8946                 int c[4];
8947                 int scale;
8948                 int size3;
8949                 const int *offsets;
8950                 const unsigned char *lm;
8951                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8952                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8953                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8954                 numvertices = 0;
8955                 for (i = 0;i < texturenumsurfaces;i++)
8956                 {
8957                         surface = texturesurfacelist[i];
8958                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8959                         surfacenumvertices = surface->num_vertices;
8960                         if (surface->lightmapinfo->samples)
8961                         {
8962                                 for (j = 0;j < surfacenumvertices;j++)
8963                                 {
8964                                         lm = surface->lightmapinfo->samples + offsets[j];
8965                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8966                                         VectorScale(lm, scale, c);
8967                                         if (surface->lightmapinfo->styles[1] != 255)
8968                                         {
8969                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8970                                                 lm += size3;
8971                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8972                                                 VectorMA(c, scale, lm, c);
8973                                                 if (surface->lightmapinfo->styles[2] != 255)
8974                                                 {
8975                                                         lm += size3;
8976                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8977                                                         VectorMA(c, scale, lm, c);
8978                                                         if (surface->lightmapinfo->styles[3] != 255)
8979                                                         {
8980                                                                 lm += size3;
8981                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8982                                                                 VectorMA(c, scale, lm, c);
8983                                                         }
8984                                                 }
8985                                         }
8986                                         c[0] >>= 7;
8987                                         c[1] >>= 7;
8988                                         c[2] >>= 7;
8989                                         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);
8990                                         numvertices++;
8991                                 }
8992                         }
8993                         else
8994                         {
8995                                 for (j = 0;j < surfacenumvertices;j++)
8996                                 {
8997                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8998                                         numvertices++;
8999                                 }
9000                         }
9001                 }
9002         }
9003
9004         // if vertices are deformed (sprite flares and things in maps, possibly
9005         // water waves, bulges and other deformations), modify the copied vertices
9006         // in place
9007         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9008         {
9009                 switch (deform->deform)
9010                 {
9011                 default:
9012                 case Q3DEFORM_PROJECTIONSHADOW:
9013                 case Q3DEFORM_TEXT0:
9014                 case Q3DEFORM_TEXT1:
9015                 case Q3DEFORM_TEXT2:
9016                 case Q3DEFORM_TEXT3:
9017                 case Q3DEFORM_TEXT4:
9018                 case Q3DEFORM_TEXT5:
9019                 case Q3DEFORM_TEXT6:
9020                 case Q3DEFORM_TEXT7:
9021                 case Q3DEFORM_NONE:
9022                         break;
9023                 case Q3DEFORM_AUTOSPRITE:
9024                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9025                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9026                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9027                         VectorNormalize(newforward);
9028                         VectorNormalize(newright);
9029                         VectorNormalize(newup);
9030 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9031 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9032 //                      rsurface.batchvertex3f_bufferoffset = 0;
9033 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9034 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9035 //                      rsurface.batchsvector3f_bufferoffset = 0;
9036 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9037 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9038 //                      rsurface.batchtvector3f_bufferoffset = 0;
9039 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9040 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9041 //                      rsurface.batchnormal3f_bufferoffset = 0;
9042                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9043                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9044                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9045                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9046                                 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);
9047                         // a single autosprite surface can contain multiple sprites...
9048                         for (j = 0;j < batchnumvertices - 3;j += 4)
9049                         {
9050                                 VectorClear(center);
9051                                 for (i = 0;i < 4;i++)
9052                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9053                                 VectorScale(center, 0.25f, center);
9054                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9055                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9056                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9057                                 for (i = 0;i < 4;i++)
9058                                 {
9059                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9060                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9061                                 }
9062                         }
9063                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9064                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9065                         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);
9066                         break;
9067                 case Q3DEFORM_AUTOSPRITE2:
9068                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9069                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9070                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9071                         VectorNormalize(newforward);
9072                         VectorNormalize(newright);
9073                         VectorNormalize(newup);
9074 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9075 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9076 //                      rsurface.batchvertex3f_bufferoffset = 0;
9077                         {
9078                                 const float *v1, *v2;
9079                                 vec3_t start, end;
9080                                 float f, l;
9081                                 struct
9082                                 {
9083                                         float length2;
9084                                         const float *v1;
9085                                         const float *v2;
9086                                 }
9087                                 shortest[2];
9088                                 memset(shortest, 0, sizeof(shortest));
9089                                 // a single autosprite surface can contain multiple sprites...
9090                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9091                                 {
9092                                         VectorClear(center);
9093                                         for (i = 0;i < 4;i++)
9094                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9095                                         VectorScale(center, 0.25f, center);
9096                                         // find the two shortest edges, then use them to define the
9097                                         // axis vectors for rotating around the central axis
9098                                         for (i = 0;i < 6;i++)
9099                                         {
9100                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9101                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9102                                                 l = VectorDistance2(v1, v2);
9103                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9104                                                 if (v1[2] != v2[2])
9105                                                         l += (1.0f / 1024.0f);
9106                                                 if (shortest[0].length2 > l || i == 0)
9107                                                 {
9108                                                         shortest[1] = shortest[0];
9109                                                         shortest[0].length2 = l;
9110                                                         shortest[0].v1 = v1;
9111                                                         shortest[0].v2 = v2;
9112                                                 }
9113                                                 else if (shortest[1].length2 > l || i == 1)
9114                                                 {
9115                                                         shortest[1].length2 = l;
9116                                                         shortest[1].v1 = v1;
9117                                                         shortest[1].v2 = v2;
9118                                                 }
9119                                         }
9120                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9121                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9122                                         // this calculates the right vector from the shortest edge
9123                                         // and the up vector from the edge midpoints
9124                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9125                                         VectorNormalize(right);
9126                                         VectorSubtract(end, start, up);
9127                                         VectorNormalize(up);
9128                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9129                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9130                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9131                                         VectorNegate(forward, forward);
9132                                         VectorReflect(forward, 0, up, forward);
9133                                         VectorNormalize(forward);
9134                                         CrossProduct(up, forward, newright);
9135                                         VectorNormalize(newright);
9136                                         // rotate the quad around the up axis vector, this is made
9137                                         // especially easy by the fact we know the quad is flat,
9138                                         // so we only have to subtract the center position and
9139                                         // measure distance along the right vector, and then
9140                                         // multiply that by the newright vector and add back the
9141                                         // center position
9142                                         // we also need to subtract the old position to undo the
9143                                         // displacement from the center, which we do with a
9144                                         // DotProduct, the subtraction/addition of center is also
9145                                         // optimized into DotProducts here
9146                                         l = DotProduct(right, center);
9147                                         for (i = 0;i < 4;i++)
9148                                         {
9149                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9150                                                 f = DotProduct(right, v1) - l;
9151                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9152                                         }
9153                                 }
9154                         }
9155                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9156                         {
9157 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9158 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9159 //                              rsurface.batchnormal3f_bufferoffset = 0;
9160                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9161                         }
9162                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9163                         {
9164 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9165 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9166 //                              rsurface.batchsvector3f_bufferoffset = 0;
9167 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9168 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9169 //                              rsurface.batchtvector3f_bufferoffset = 0;
9170                                 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);
9171                         }
9172                         break;
9173                 case Q3DEFORM_NORMAL:
9174                         // deform the normals to make reflections wavey
9175                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9176                         rsurface.batchnormal3f_vertexbuffer = NULL;
9177                         rsurface.batchnormal3f_bufferoffset = 0;
9178                         for (j = 0;j < batchnumvertices;j++)
9179                         {
9180                                 float vertex[3];
9181                                 float *normal = rsurface.batchnormal3f + 3*j;
9182                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9183                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9184                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9185                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9186                                 VectorNormalize(normal);
9187                         }
9188                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9189                         {
9190 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9191 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9192 //                              rsurface.batchsvector3f_bufferoffset = 0;
9193 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9194 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9195 //                              rsurface.batchtvector3f_bufferoffset = 0;
9196                                 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);
9197                         }
9198                         break;
9199                 case Q3DEFORM_WAVE:
9200                         // deform vertex array to make wavey water and flags and such
9201                         waveparms[0] = deform->waveparms[0];
9202                         waveparms[1] = deform->waveparms[1];
9203                         waveparms[2] = deform->waveparms[2];
9204                         waveparms[3] = deform->waveparms[3];
9205                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9206                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9207                         // this is how a divisor of vertex influence on deformation
9208                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9209                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9210 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9211 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9212 //                      rsurface.batchvertex3f_bufferoffset = 0;
9213 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9214 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9215 //                      rsurface.batchnormal3f_bufferoffset = 0;
9216                         for (j = 0;j < batchnumvertices;j++)
9217                         {
9218                                 // if the wavefunc depends on time, evaluate it per-vertex
9219                                 if (waveparms[3])
9220                                 {
9221                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9222                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9223                                 }
9224                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9225                         }
9226                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9227                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9228                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9229                         {
9230 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9231 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9232 //                              rsurface.batchsvector3f_bufferoffset = 0;
9233 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9234 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9235 //                              rsurface.batchtvector3f_bufferoffset = 0;
9236                                 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);
9237                         }
9238                         break;
9239                 case Q3DEFORM_BULGE:
9240                         // deform vertex array to make the surface have moving bulges
9241 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9242 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9243 //                      rsurface.batchvertex3f_bufferoffset = 0;
9244 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9245 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9246 //                      rsurface.batchnormal3f_bufferoffset = 0;
9247                         for (j = 0;j < batchnumvertices;j++)
9248                         {
9249                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9250                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9251                         }
9252                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9253                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9254                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9255                         {
9256 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9257 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9258 //                              rsurface.batchsvector3f_bufferoffset = 0;
9259 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9260 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9261 //                              rsurface.batchtvector3f_bufferoffset = 0;
9262                                 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);
9263                         }
9264                         break;
9265                 case Q3DEFORM_MOVE:
9266                         // deform vertex array
9267                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9268                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9269                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9270                         VectorScale(deform->parms, scale, waveparms);
9271 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9272 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9273 //                      rsurface.batchvertex3f_bufferoffset = 0;
9274                         for (j = 0;j < batchnumvertices;j++)
9275                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9276                         break;
9277                 }
9278         }
9279
9280         // generate texcoords based on the chosen texcoord source
9281         switch(rsurface.texture->tcgen.tcgen)
9282         {
9283         default:
9284         case Q3TCGEN_TEXTURE:
9285                 break;
9286         case Q3TCGEN_LIGHTMAP:
9287 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9288 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9289 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9290                 if (rsurface.batchtexcoordlightmap2f)
9291                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9292                 break;
9293         case Q3TCGEN_VECTOR:
9294 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9295 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9296 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9297                 for (j = 0;j < batchnumvertices;j++)
9298                 {
9299                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9300                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9301                 }
9302                 break;
9303         case Q3TCGEN_ENVIRONMENT:
9304                 // make environment reflections using a spheremap
9305                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9306                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9307                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9308                 for (j = 0;j < batchnumvertices;j++)
9309                 {
9310                         // identical to Q3A's method, but executed in worldspace so
9311                         // carried models can be shiny too
9312
9313                         float viewer[3], d, reflected[3], worldreflected[3];
9314
9315                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9316                         // VectorNormalize(viewer);
9317
9318                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9319
9320                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9321                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9322                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9323                         // note: this is proportinal to viewer, so we can normalize later
9324
9325                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9326                         VectorNormalize(worldreflected);
9327
9328                         // note: this sphere map only uses world x and z!
9329                         // so positive and negative y will LOOK THE SAME.
9330                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9331                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9332                 }
9333                 break;
9334         }
9335         // the only tcmod that needs software vertex processing is turbulent, so
9336         // check for it here and apply the changes if needed
9337         // and we only support that as the first one
9338         // (handling a mixture of turbulent and other tcmods would be problematic
9339         //  without punting it entirely to a software path)
9340         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9341         {
9342                 amplitude = rsurface.texture->tcmods[0].parms[1];
9343                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9344 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9345 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9346 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9347                 for (j = 0;j < batchnumvertices;j++)
9348                 {
9349                         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);
9350                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9351                 }
9352         }
9353
9354         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9355         {
9356                 // convert the modified arrays to vertex structs
9357 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9358 //              rsurface.batchvertexmeshbuffer = NULL;
9359                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9360                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9361                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9362                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9363                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9364                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9365                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9366                 {
9367                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9368                         {
9369                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9370                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9371                         }
9372                 }
9373                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9374                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9375                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9376                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9377                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9378                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9379                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9380                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9381                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9382         }
9383 }
9384
9385 void RSurf_DrawBatch(void)
9386 {
9387         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9388         // through the pipeline, killing it earlier in the pipeline would have
9389         // per-surface overhead rather than per-batch overhead, so it's best to
9390         // reject it here, before it hits glDraw.
9391         if (rsurface.batchnumtriangles == 0)
9392                 return;
9393 #if 0
9394         // batch debugging code
9395         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9396         {
9397                 int i;
9398                 int j;
9399                 int c;
9400                 const int *e;
9401                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9402                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9403                 {
9404                         c = e[i];
9405                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9406                         {
9407                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9408                                 {
9409                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9410                                                 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);
9411                                         break;
9412                                 }
9413                         }
9414                 }
9415         }
9416 #endif
9417         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);
9418 }
9419
9420 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9421 {
9422         // pick the closest matching water plane
9423         int planeindex, vertexindex, bestplaneindex = -1;
9424         float d, bestd;
9425         vec3_t vert;
9426         const float *v;
9427         r_waterstate_waterplane_t *p;
9428         qboolean prepared = false;
9429         bestd = 0;
9430         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9431         {
9432                 if(p->camera_entity != rsurface.texture->camera_entity)
9433                         continue;
9434                 d = 0;
9435                 if(!prepared)
9436                 {
9437                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9438                         prepared = true;
9439                         if(rsurface.batchnumvertices == 0)
9440                                 break;
9441                 }
9442                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9443                 {
9444                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9445                         d += fabs(PlaneDiff(vert, &p->plane));
9446                 }
9447                 if (bestd > d || bestplaneindex < 0)
9448                 {
9449                         bestd = d;
9450                         bestplaneindex = planeindex;
9451                 }
9452         }
9453         return bestplaneindex;
9454         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9455         // this situation though, as it might be better to render single larger
9456         // batches with useless stuff (backface culled for example) than to
9457         // render multiple smaller batches
9458 }
9459
9460 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9461 {
9462         int i;
9463         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9464         rsurface.passcolor4f_vertexbuffer = 0;
9465         rsurface.passcolor4f_bufferoffset = 0;
9466         for (i = 0;i < rsurface.batchnumvertices;i++)
9467                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9468 }
9469
9470 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9471 {
9472         int i;
9473         float f;
9474         const float *v;
9475         const float *c;
9476         float *c2;
9477         if (rsurface.passcolor4f)
9478         {
9479                 // generate color arrays
9480                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9481                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9482                 rsurface.passcolor4f_vertexbuffer = 0;
9483                 rsurface.passcolor4f_bufferoffset = 0;
9484                 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)
9485                 {
9486                         f = RSurf_FogVertex(v);
9487                         c2[0] = c[0] * f;
9488                         c2[1] = c[1] * f;
9489                         c2[2] = c[2] * f;
9490                         c2[3] = c[3];
9491                 }
9492         }
9493         else
9494         {
9495                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9496                 rsurface.passcolor4f_vertexbuffer = 0;
9497                 rsurface.passcolor4f_bufferoffset = 0;
9498                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9499                 {
9500                         f = RSurf_FogVertex(v);
9501                         c2[0] = f;
9502                         c2[1] = f;
9503                         c2[2] = f;
9504                         c2[3] = 1;
9505                 }
9506         }
9507 }
9508
9509 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9510 {
9511         int i;
9512         float f;
9513         const float *v;
9514         const float *c;
9515         float *c2;
9516         if (!rsurface.passcolor4f)
9517                 return;
9518         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9519         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9520         rsurface.passcolor4f_vertexbuffer = 0;
9521         rsurface.passcolor4f_bufferoffset = 0;
9522         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)
9523         {
9524                 f = RSurf_FogVertex(v);
9525                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9526                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9527                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9528                 c2[3] = c[3];
9529         }
9530 }
9531
9532 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9533 {
9534         int i;
9535         const float *c;
9536         float *c2;
9537         if (!rsurface.passcolor4f)
9538                 return;
9539         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9540         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9541         rsurface.passcolor4f_vertexbuffer = 0;
9542         rsurface.passcolor4f_bufferoffset = 0;
9543         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9544         {
9545                 c2[0] = c[0] * r;
9546                 c2[1] = c[1] * g;
9547                 c2[2] = c[2] * b;
9548                 c2[3] = c[3] * a;
9549         }
9550 }
9551
9552 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9553 {
9554         int i;
9555         const float *c;
9556         float *c2;
9557         if (!rsurface.passcolor4f)
9558                 return;
9559         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9560         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9561         rsurface.passcolor4f_vertexbuffer = 0;
9562         rsurface.passcolor4f_bufferoffset = 0;
9563         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9564         {
9565                 c2[0] = c[0] + r_refdef.scene.ambient;
9566                 c2[1] = c[1] + r_refdef.scene.ambient;
9567                 c2[2] = c[2] + r_refdef.scene.ambient;
9568                 c2[3] = c[3];
9569         }
9570 }
9571
9572 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9573 {
9574         // TODO: optimize
9575         rsurface.passcolor4f = NULL;
9576         rsurface.passcolor4f_vertexbuffer = 0;
9577         rsurface.passcolor4f_bufferoffset = 0;
9578         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9579         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9580         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9581         GL_Color(r, g, b, a);
9582         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9583         RSurf_DrawBatch();
9584 }
9585
9586 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9587 {
9588         // TODO: optimize applyfog && applycolor case
9589         // just apply fog if necessary, and tint the fog color array if necessary
9590         rsurface.passcolor4f = NULL;
9591         rsurface.passcolor4f_vertexbuffer = 0;
9592         rsurface.passcolor4f_bufferoffset = 0;
9593         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9594         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9595         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9596         GL_Color(r, g, b, a);
9597         RSurf_DrawBatch();
9598 }
9599
9600 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9601 {
9602         // TODO: optimize
9603         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9604         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9605         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9606         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9607         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9608         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9609         GL_Color(r, g, b, a);
9610         RSurf_DrawBatch();
9611 }
9612
9613 static void RSurf_DrawBatch_GL11_ClampColor(void)
9614 {
9615         int i;
9616         const float *c1;
9617         float *c2;
9618         if (!rsurface.passcolor4f)
9619                 return;
9620         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9621         {
9622                 c2[0] = bound(0.0f, c1[0], 1.0f);
9623                 c2[1] = bound(0.0f, c1[1], 1.0f);
9624                 c2[2] = bound(0.0f, c1[2], 1.0f);
9625                 c2[3] = bound(0.0f, c1[3], 1.0f);
9626         }
9627 }
9628
9629 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9630 {
9631         int i;
9632         float f;
9633         const float *v;
9634         const float *n;
9635         float *c;
9636         //vec3_t eyedir;
9637
9638         // fake shading
9639         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9640         rsurface.passcolor4f_vertexbuffer = 0;
9641         rsurface.passcolor4f_bufferoffset = 0;
9642         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)
9643         {
9644                 f = -DotProduct(r_refdef.view.forward, n);
9645                 f = max(0, f);
9646                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9647                 f *= r_refdef.lightmapintensity;
9648                 Vector4Set(c, f, f, f, 1);
9649         }
9650 }
9651
9652 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9653 {
9654         RSurf_DrawBatch_GL11_ApplyFakeLight();
9655         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9656         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9657         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9658         GL_Color(r, g, b, a);
9659         RSurf_DrawBatch();
9660 }
9661
9662 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9663 {
9664         int i;
9665         float f;
9666         float alpha;
9667         const float *v;
9668         const float *n;
9669         float *c;
9670         vec3_t ambientcolor;
9671         vec3_t diffusecolor;
9672         vec3_t lightdir;
9673         // TODO: optimize
9674         // model lighting
9675         VectorCopy(rsurface.modellight_lightdir, lightdir);
9676         f = 0.5f * r_refdef.lightmapintensity;
9677         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9678         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9679         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9680         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9681         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9682         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9683         alpha = *a;
9684         if (VectorLength2(diffusecolor) > 0)
9685         {
9686                 // q3-style directional shading
9687                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9688                 rsurface.passcolor4f_vertexbuffer = 0;
9689                 rsurface.passcolor4f_bufferoffset = 0;
9690                 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)
9691                 {
9692                         if ((f = DotProduct(n, lightdir)) > 0)
9693                                 VectorMA(ambientcolor, f, diffusecolor, c);
9694                         else
9695                                 VectorCopy(ambientcolor, c);
9696                         c[3] = alpha;
9697                 }
9698                 *r = 1;
9699                 *g = 1;
9700                 *b = 1;
9701                 *a = 1;
9702                 *applycolor = false;
9703         }
9704         else
9705         {
9706                 *r = ambientcolor[0];
9707                 *g = ambientcolor[1];
9708                 *b = ambientcolor[2];
9709                 rsurface.passcolor4f = NULL;
9710                 rsurface.passcolor4f_vertexbuffer = 0;
9711                 rsurface.passcolor4f_bufferoffset = 0;
9712         }
9713 }
9714
9715 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9716 {
9717         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9718         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9719         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9720         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9721         GL_Color(r, g, b, a);
9722         RSurf_DrawBatch();
9723 }
9724
9725 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9726 {
9727         int i;
9728         float f;
9729         const float *v;
9730         float *c;
9731
9732         // fake shading
9733         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9734         rsurface.passcolor4f_vertexbuffer = 0;
9735         rsurface.passcolor4f_bufferoffset = 0;
9736
9737         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9738         {
9739                 f = 1 - RSurf_FogVertex(v);
9740                 c[0] = r;
9741                 c[1] = g;
9742                 c[2] = b;
9743                 c[3] = f * a;
9744         }
9745 }
9746
9747 void RSurf_SetupDepthAndCulling(void)
9748 {
9749         // submodels are biased to avoid z-fighting with world surfaces that they
9750         // may be exactly overlapping (avoids z-fighting artifacts on certain
9751         // doors and things in Quake maps)
9752         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9753         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9754         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9755         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9756 }
9757
9758 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9759 {
9760         // transparent sky would be ridiculous
9761         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9762                 return;
9763         R_SetupShader_Generic_NoTexture(false, false);
9764         skyrenderlater = true;
9765         RSurf_SetupDepthAndCulling();
9766         GL_DepthMask(true);
9767         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9768         // skymasking on them, and Quake3 never did sky masking (unlike
9769         // software Quake and software Quake2), so disable the sky masking
9770         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9771         // and skymasking also looks very bad when noclipping outside the
9772         // level, so don't use it then either.
9773         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9774         {
9775                 R_Mesh_ResetTextureState();
9776                 if (skyrendermasked)
9777                 {
9778                         R_SetupShader_DepthOrShadow(false, false);
9779                         // depth-only (masking)
9780                         GL_ColorMask(0,0,0,0);
9781                         // just to make sure that braindead drivers don't draw
9782                         // anything despite that colormask...
9783                         GL_BlendFunc(GL_ZERO, GL_ONE);
9784                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9785                         if (rsurface.batchvertex3fbuffer)
9786                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9787                         else
9788                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9789                 }
9790                 else
9791                 {
9792                         R_SetupShader_Generic_NoTexture(false, false);
9793                         // fog sky
9794                         GL_BlendFunc(GL_ONE, GL_ZERO);
9795                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9796                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9797                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9798                 }
9799                 RSurf_DrawBatch();
9800                 if (skyrendermasked)
9801                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9802         }
9803         R_Mesh_ResetTextureState();
9804         GL_Color(1, 1, 1, 1);
9805 }
9806
9807 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9808 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9809 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9810 {
9811         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9812                 return;
9813         if (prepass)
9814         {
9815                 // render screenspace normalmap to texture
9816                 GL_DepthMask(true);
9817                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9818                 RSurf_DrawBatch();
9819                 return;
9820         }
9821
9822         // bind lightmap texture
9823
9824         // water/refraction/reflection/camera surfaces have to be handled specially
9825         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9826         {
9827                 int start, end, startplaneindex;
9828                 for (start = 0;start < texturenumsurfaces;start = end)
9829                 {
9830                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9831                         if(startplaneindex < 0)
9832                         {
9833                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9834                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9835                                 end = start + 1;
9836                                 continue;
9837                         }
9838                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9839                                 ;
9840                         // now that we have a batch using the same planeindex, render it
9841                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9842                         {
9843                                 // render water or distortion background
9844                                 GL_DepthMask(true);
9845                                 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);
9846                                 RSurf_DrawBatch();
9847                                 // blend surface on top
9848                                 GL_DepthMask(false);
9849                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9850                                 RSurf_DrawBatch();
9851                         }
9852                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9853                         {
9854                                 // render surface with reflection texture as input
9855                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9856                                 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);
9857                                 RSurf_DrawBatch();
9858                         }
9859                 }
9860                 return;
9861         }
9862
9863         // render surface batch normally
9864         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9865         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);
9866         RSurf_DrawBatch();
9867 }
9868
9869 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9870 {
9871         // OpenGL 1.3 path - anything not completely ancient
9872         qboolean applycolor;
9873         qboolean applyfog;
9874         int layerindex;
9875         const texturelayer_t *layer;
9876         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);
9877         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9878
9879         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9880         {
9881                 vec4_t layercolor;
9882                 int layertexrgbscale;
9883                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9884                 {
9885                         if (layerindex == 0)
9886                                 GL_AlphaTest(true);
9887                         else
9888                         {
9889                                 GL_AlphaTest(false);
9890                                 GL_DepthFunc(GL_EQUAL);
9891                         }
9892                 }
9893                 GL_DepthMask(layer->depthmask && writedepth);
9894                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9895                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9896                 {
9897                         layertexrgbscale = 4;
9898                         VectorScale(layer->color, 0.25f, layercolor);
9899                 }
9900                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9901                 {
9902                         layertexrgbscale = 2;
9903                         VectorScale(layer->color, 0.5f, layercolor);
9904                 }
9905                 else
9906                 {
9907                         layertexrgbscale = 1;
9908                         VectorScale(layer->color, 1.0f, layercolor);
9909                 }
9910                 layercolor[3] = layer->color[3];
9911                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9912                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9913                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9914                 switch (layer->type)
9915                 {
9916                 case TEXTURELAYERTYPE_LITTEXTURE:
9917                         // single-pass lightmapped texture with 2x rgbscale
9918                         R_Mesh_TexBind(0, r_texture_white);
9919                         R_Mesh_TexMatrix(0, NULL);
9920                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9921                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9922                         R_Mesh_TexBind(1, layer->texture);
9923                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9924                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9925                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9926                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9927                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9928                         else if (FAKELIGHT_ENABLED)
9929                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9930                         else if (rsurface.uselightmaptexture)
9931                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9932                         else
9933                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9934                         break;
9935                 case TEXTURELAYERTYPE_TEXTURE:
9936                         // singletexture unlit texture with transparency support
9937                         R_Mesh_TexBind(0, layer->texture);
9938                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9939                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9940                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9941                         R_Mesh_TexBind(1, 0);
9942                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9943                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9944                         break;
9945                 case TEXTURELAYERTYPE_FOG:
9946                         // singletexture fogging
9947                         if (layer->texture)
9948                         {
9949                                 R_Mesh_TexBind(0, layer->texture);
9950                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9951                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9952                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9953                         }
9954                         else
9955                         {
9956                                 R_Mesh_TexBind(0, 0);
9957                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9958                         }
9959                         R_Mesh_TexBind(1, 0);
9960                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9961                         // generate a color array for the fog pass
9962                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9963                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9964                         RSurf_DrawBatch();
9965                         break;
9966                 default:
9967                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9968                 }
9969         }
9970         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9971         {
9972                 GL_DepthFunc(GL_LEQUAL);
9973                 GL_AlphaTest(false);
9974         }
9975 }
9976
9977 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9978 {
9979         // OpenGL 1.1 - crusty old voodoo path
9980         qboolean applyfog;
9981         int layerindex;
9982         const texturelayer_t *layer;
9983         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);
9984         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9985
9986         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9987         {
9988                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9989                 {
9990                         if (layerindex == 0)
9991                                 GL_AlphaTest(true);
9992                         else
9993                         {
9994                                 GL_AlphaTest(false);
9995                                 GL_DepthFunc(GL_EQUAL);
9996                         }
9997                 }
9998                 GL_DepthMask(layer->depthmask && writedepth);
9999                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10000                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10001                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10002                 switch (layer->type)
10003                 {
10004                 case TEXTURELAYERTYPE_LITTEXTURE:
10005                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10006                         {
10007                                 // two-pass lit texture with 2x rgbscale
10008                                 // first the lightmap pass
10009                                 R_Mesh_TexBind(0, r_texture_white);
10010                                 R_Mesh_TexMatrix(0, NULL);
10011                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10012                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10013                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10014                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10015                                 else if (FAKELIGHT_ENABLED)
10016                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10017                                 else if (rsurface.uselightmaptexture)
10018                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10019                                 else
10020                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10021                                 // then apply the texture to it
10022                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10023                                 R_Mesh_TexBind(0, layer->texture);
10024                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10025                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10026                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10027                                 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);
10028                         }
10029                         else
10030                         {
10031                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10032                                 R_Mesh_TexBind(0, layer->texture);
10033                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10034                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10035                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10036                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10037                                         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);
10038                                 else
10039                                         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);
10040                         }
10041                         break;
10042                 case TEXTURELAYERTYPE_TEXTURE:
10043                         // singletexture unlit texture with transparency support
10044                         R_Mesh_TexBind(0, layer->texture);
10045                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10046                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10047                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10048                         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);
10049                         break;
10050                 case TEXTURELAYERTYPE_FOG:
10051                         // singletexture fogging
10052                         if (layer->texture)
10053                         {
10054                                 R_Mesh_TexBind(0, layer->texture);
10055                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10056                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10057                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10058                         }
10059                         else
10060                         {
10061                                 R_Mesh_TexBind(0, 0);
10062                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10063                         }
10064                         // generate a color array for the fog pass
10065                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10066                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10067                         RSurf_DrawBatch();
10068                         break;
10069                 default:
10070                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10071                 }
10072         }
10073         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10074         {
10075                 GL_DepthFunc(GL_LEQUAL);
10076                 GL_AlphaTest(false);
10077         }
10078 }
10079
10080 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10081 {
10082         int vi;
10083         int j;
10084         r_vertexgeneric_t *batchvertex;
10085         float c[4];
10086
10087 //      R_Mesh_ResetTextureState();
10088         R_SetupShader_Generic_NoTexture(false, false);
10089
10090         if(rsurface.texture && rsurface.texture->currentskinframe)
10091         {
10092                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10093                 c[3] *= rsurface.texture->currentalpha;
10094         }
10095         else
10096         {
10097                 c[0] = 1;
10098                 c[1] = 0;
10099                 c[2] = 1;
10100                 c[3] = 1;
10101         }
10102
10103         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10104         {
10105                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10106                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10107                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10108         }
10109
10110         // brighten it up (as texture value 127 means "unlit")
10111         c[0] *= 2 * r_refdef.view.colorscale;
10112         c[1] *= 2 * r_refdef.view.colorscale;
10113         c[2] *= 2 * r_refdef.view.colorscale;
10114
10115         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10116                 c[3] *= r_wateralpha.value;
10117
10118         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10119         {
10120                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10121                 GL_DepthMask(false);
10122         }
10123         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10124         {
10125                 GL_BlendFunc(GL_ONE, GL_ONE);
10126                 GL_DepthMask(false);
10127         }
10128         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10129         {
10130                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10131                 GL_DepthMask(false);
10132         }
10133         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10134         {
10135                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10136                 GL_DepthMask(false);
10137         }
10138         else
10139         {
10140                 GL_BlendFunc(GL_ONE, GL_ZERO);
10141                 GL_DepthMask(writedepth);
10142         }
10143
10144         if (r_showsurfaces.integer == 3)
10145         {
10146                 rsurface.passcolor4f = NULL;
10147
10148                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10149                 {
10150                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10151
10152                         rsurface.passcolor4f = NULL;
10153                         rsurface.passcolor4f_vertexbuffer = 0;
10154                         rsurface.passcolor4f_bufferoffset = 0;
10155                 }
10156                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10157                 {
10158                         qboolean applycolor = true;
10159                         float one = 1.0;
10160
10161                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10162
10163                         r_refdef.lightmapintensity = 1;
10164                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10165                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10166                 }
10167                 else if (FAKELIGHT_ENABLED)
10168                 {
10169                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10170
10171                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10172                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10173                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10174                 }
10175                 else
10176                 {
10177                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10178
10179                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10180                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10181                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10182                 }
10183
10184                 if(!rsurface.passcolor4f)
10185                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10186
10187                 RSurf_DrawBatch_GL11_ApplyAmbient();
10188                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10189                 if(r_refdef.fogenabled)
10190                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10191                 RSurf_DrawBatch_GL11_ClampColor();
10192
10193                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10194                 R_SetupShader_Generic_NoTexture(false, false);
10195                 RSurf_DrawBatch();
10196         }
10197         else if (!r_refdef.view.showdebug)
10198         {
10199                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10200                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10201                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10202                 {
10203                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10204                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10205                 }
10206                 R_Mesh_PrepareVertices_Generic_Unlock();
10207                 RSurf_DrawBatch();
10208         }
10209         else if (r_showsurfaces.integer == 4)
10210         {
10211                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10212                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10213                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10214                 {
10215                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10216                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10217                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10218                 }
10219                 R_Mesh_PrepareVertices_Generic_Unlock();
10220                 RSurf_DrawBatch();
10221         }
10222         else if (r_showsurfaces.integer == 2)
10223         {
10224                 const int *e;
10225                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10226                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10227                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10228                 {
10229                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10230                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10231                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10232                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10233                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10234                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10235                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10236                 }
10237                 R_Mesh_PrepareVertices_Generic_Unlock();
10238                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10239         }
10240         else
10241         {
10242                 int texturesurfaceindex;
10243                 int k;
10244                 const msurface_t *surface;
10245                 float surfacecolor4f[4];
10246                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10247                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10248                 vi = 0;
10249                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10250                 {
10251                         surface = texturesurfacelist[texturesurfaceindex];
10252                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10253                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10254                         for (j = 0;j < surface->num_vertices;j++)
10255                         {
10256                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10257                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10258                                 vi++;
10259                         }
10260                 }
10261                 R_Mesh_PrepareVertices_Generic_Unlock();
10262                 RSurf_DrawBatch();
10263         }
10264 }
10265
10266 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10267 {
10268         CHECKGLERROR
10269         RSurf_SetupDepthAndCulling();
10270         if (r_showsurfaces.integer)
10271         {
10272                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10273                 return;
10274         }
10275         switch (vid.renderpath)
10276         {
10277         case RENDERPATH_GL20:
10278         case RENDERPATH_D3D9:
10279         case RENDERPATH_D3D10:
10280         case RENDERPATH_D3D11:
10281         case RENDERPATH_SOFT:
10282         case RENDERPATH_GLES2:
10283                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10284                 break;
10285         case RENDERPATH_GL13:
10286         case RENDERPATH_GLES1:
10287                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10288                 break;
10289         case RENDERPATH_GL11:
10290                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10291                 break;
10292         }
10293         CHECKGLERROR
10294 }
10295
10296 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10297 {
10298         CHECKGLERROR
10299         RSurf_SetupDepthAndCulling();
10300         if (r_showsurfaces.integer)
10301         {
10302                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10303                 return;
10304         }
10305         switch (vid.renderpath)
10306         {
10307         case RENDERPATH_GL20:
10308         case RENDERPATH_D3D9:
10309         case RENDERPATH_D3D10:
10310         case RENDERPATH_D3D11:
10311         case RENDERPATH_SOFT:
10312         case RENDERPATH_GLES2:
10313                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10314                 break;
10315         case RENDERPATH_GL13:
10316         case RENDERPATH_GLES1:
10317                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10318                 break;
10319         case RENDERPATH_GL11:
10320                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10321                 break;
10322         }
10323         CHECKGLERROR
10324 }
10325
10326 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10327 {
10328         int i, j;
10329         int texturenumsurfaces, endsurface;
10330         texture_t *texture;
10331         const msurface_t *surface;
10332         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10333
10334         // if the model is static it doesn't matter what value we give for
10335         // wantnormals and wanttangents, so this logic uses only rules applicable
10336         // to a model, knowing that they are meaningless otherwise
10337         if (ent == r_refdef.scene.worldentity)
10338                 RSurf_ActiveWorldEntity();
10339         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10340                 RSurf_ActiveModelEntity(ent, false, false, false);
10341         else
10342         {
10343                 switch (vid.renderpath)
10344                 {
10345                 case RENDERPATH_GL20:
10346                 case RENDERPATH_D3D9:
10347                 case RENDERPATH_D3D10:
10348                 case RENDERPATH_D3D11:
10349                 case RENDERPATH_SOFT:
10350                 case RENDERPATH_GLES2:
10351                         RSurf_ActiveModelEntity(ent, true, true, false);
10352                         break;
10353                 case RENDERPATH_GL11:
10354                 case RENDERPATH_GL13:
10355                 case RENDERPATH_GLES1:
10356                         RSurf_ActiveModelEntity(ent, true, false, false);
10357                         break;
10358                 }
10359         }
10360
10361         if (r_transparentdepthmasking.integer)
10362         {
10363                 qboolean setup = false;
10364                 for (i = 0;i < numsurfaces;i = j)
10365                 {
10366                         j = i + 1;
10367                         surface = rsurface.modelsurfaces + surfacelist[i];
10368                         texture = surface->texture;
10369                         rsurface.texture = R_GetCurrentTexture(texture);
10370                         rsurface.lightmaptexture = NULL;
10371                         rsurface.deluxemaptexture = NULL;
10372                         rsurface.uselightmaptexture = false;
10373                         // scan ahead until we find a different texture
10374                         endsurface = min(i + 1024, numsurfaces);
10375                         texturenumsurfaces = 0;
10376                         texturesurfacelist[texturenumsurfaces++] = surface;
10377                         for (;j < endsurface;j++)
10378                         {
10379                                 surface = rsurface.modelsurfaces + surfacelist[j];
10380                                 if (texture != surface->texture)
10381                                         break;
10382                                 texturesurfacelist[texturenumsurfaces++] = surface;
10383                         }
10384                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10385                                 continue;
10386                         // render the range of surfaces as depth
10387                         if (!setup)
10388                         {
10389                                 setup = true;
10390                                 GL_ColorMask(0,0,0,0);
10391                                 GL_Color(1,1,1,1);
10392                                 GL_DepthTest(true);
10393                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10394                                 GL_DepthMask(true);
10395 //                              R_Mesh_ResetTextureState();
10396                                 R_SetupShader_DepthOrShadow(false, false);
10397                         }
10398                         RSurf_SetupDepthAndCulling();
10399                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10400                         if (rsurface.batchvertex3fbuffer)
10401                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10402                         else
10403                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10404                         RSurf_DrawBatch();
10405                 }
10406                 if (setup)
10407                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10408         }
10409
10410         for (i = 0;i < numsurfaces;i = j)
10411         {
10412                 j = i + 1;
10413                 surface = rsurface.modelsurfaces + surfacelist[i];
10414                 texture = surface->texture;
10415                 rsurface.texture = R_GetCurrentTexture(texture);
10416                 // scan ahead until we find a different texture
10417                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10418                 texturenumsurfaces = 0;
10419                 texturesurfacelist[texturenumsurfaces++] = surface;
10420                 if(FAKELIGHT_ENABLED)
10421                 {
10422                         rsurface.lightmaptexture = NULL;
10423                         rsurface.deluxemaptexture = NULL;
10424                         rsurface.uselightmaptexture = false;
10425                         for (;j < endsurface;j++)
10426                         {
10427                                 surface = rsurface.modelsurfaces + surfacelist[j];
10428                                 if (texture != surface->texture)
10429                                         break;
10430                                 texturesurfacelist[texturenumsurfaces++] = surface;
10431                         }
10432                 }
10433                 else
10434                 {
10435                         rsurface.lightmaptexture = surface->lightmaptexture;
10436                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10437                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10438                         for (;j < endsurface;j++)
10439                         {
10440                                 surface = rsurface.modelsurfaces + surfacelist[j];
10441                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10442                                         break;
10443                                 texturesurfacelist[texturenumsurfaces++] = surface;
10444                         }
10445                 }
10446                 // render the range of surfaces
10447                 if (ent == r_refdef.scene.worldentity)
10448                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10449                 else
10450                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10451         }
10452         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10453 }
10454
10455 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10456 {
10457         // transparent surfaces get pushed off into the transparent queue
10458         int surfacelistindex;
10459         const msurface_t *surface;
10460         vec3_t tempcenter, center;
10461         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10462         {
10463                 surface = texturesurfacelist[surfacelistindex];
10464                 if (r_transparent_sortsurfacesbynearest.integer)
10465                 {
10466                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10467                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10468                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10469                 }
10470                 else
10471                 {
10472                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10473                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10474                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10475                 }
10476                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10477                 if (rsurface.entity->transparent_offset) // transparent offset
10478                 {
10479                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10480                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10481                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10482                 }
10483                 R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10484         }
10485 }
10486
10487 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10488 {
10489         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10490                 return;
10491         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10492                 return;
10493         RSurf_SetupDepthAndCulling();
10494         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10495         if (rsurface.batchvertex3fbuffer)
10496                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10497         else
10498                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10499         RSurf_DrawBatch();
10500 }
10501
10502 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10503 {
10504         CHECKGLERROR
10505         if (depthonly)
10506                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10507         else if (prepass)
10508         {
10509                 if (!rsurface.texture->currentnumlayers)
10510                         return;
10511                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10512                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10513                 else
10514                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10515         }
10516         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10517                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10518         else if (!rsurface.texture->currentnumlayers)
10519                 return;
10520         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10521         {
10522                 // in the deferred case, transparent surfaces were queued during prepass
10523                 if (!r_shadow_usingdeferredprepass)
10524                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10525         }
10526         else
10527         {
10528                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10529                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10530         }
10531         CHECKGLERROR
10532 }
10533
10534 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10535 {
10536         int i, j;
10537         texture_t *texture;
10538         R_FrameData_SetMark();
10539         // break the surface list down into batches by texture and use of lightmapping
10540         for (i = 0;i < numsurfaces;i = j)
10541         {
10542                 j = i + 1;
10543                 // texture is the base texture pointer, rsurface.texture is the
10544                 // current frame/skin the texture is directing us to use (for example
10545                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10546                 // use skin 1 instead)
10547                 texture = surfacelist[i]->texture;
10548                 rsurface.texture = R_GetCurrentTexture(texture);
10549                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10550                 {
10551                         // if this texture is not the kind we want, skip ahead to the next one
10552                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10553                                 ;
10554                         continue;
10555                 }
10556                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10557                 {
10558                         rsurface.lightmaptexture = NULL;
10559                         rsurface.deluxemaptexture = NULL;
10560                         rsurface.uselightmaptexture = false;
10561                         // simply scan ahead until we find a different texture or lightmap state
10562                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10563                                 ;
10564                 }
10565                 else
10566                 {
10567                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10568                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10569                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10570                         // simply scan ahead until we find a different texture or lightmap state
10571                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10572                                 ;
10573                 }
10574                 // render the range of surfaces
10575                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10576         }
10577         R_FrameData_ReturnToMark();
10578 }
10579
10580 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10581 {
10582         CHECKGLERROR
10583         if (depthonly)
10584                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10585         else if (prepass)
10586         {
10587                 if (!rsurface.texture->currentnumlayers)
10588                         return;
10589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10590                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10591                 else
10592                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10593         }
10594         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10595                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10596         else if (!rsurface.texture->currentnumlayers)
10597                 return;
10598         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10599         {
10600                 // in the deferred case, transparent surfaces were queued during prepass
10601                 if (!r_shadow_usingdeferredprepass)
10602                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10603         }
10604         else
10605         {
10606                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10607                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10608         }
10609         CHECKGLERROR
10610 }
10611
10612 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10613 {
10614         int i, j;
10615         texture_t *texture;
10616         R_FrameData_SetMark();
10617         // break the surface list down into batches by texture and use of lightmapping
10618         for (i = 0;i < numsurfaces;i = j)
10619         {
10620                 j = i + 1;
10621                 // texture is the base texture pointer, rsurface.texture is the
10622                 // current frame/skin the texture is directing us to use (for example
10623                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10624                 // use skin 1 instead)
10625                 texture = surfacelist[i]->texture;
10626                 rsurface.texture = R_GetCurrentTexture(texture);
10627                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10628                 {
10629                         // if this texture is not the kind we want, skip ahead to the next one
10630                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10631                                 ;
10632                         continue;
10633                 }
10634                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10635                 {
10636                         rsurface.lightmaptexture = NULL;
10637                         rsurface.deluxemaptexture = NULL;
10638                         rsurface.uselightmaptexture = false;
10639                         // simply scan ahead until we find a different texture or lightmap state
10640                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10641                                 ;
10642                 }
10643                 else
10644                 {
10645                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10646                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10647                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10648                         // simply scan ahead until we find a different texture or lightmap state
10649                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10650                                 ;
10651                 }
10652                 // render the range of surfaces
10653                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10654         }
10655         R_FrameData_ReturnToMark();
10656 }
10657
10658 float locboxvertex3f[6*4*3] =
10659 {
10660         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10661         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10662         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10663         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10664         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10665         1,0,0, 0,0,0, 0,1,0, 1,1,0
10666 };
10667
10668 unsigned short locboxelements[6*2*3] =
10669 {
10670          0, 1, 2, 0, 2, 3,
10671          4, 5, 6, 4, 6, 7,
10672          8, 9,10, 8,10,11,
10673         12,13,14, 12,14,15,
10674         16,17,18, 16,18,19,
10675         20,21,22, 20,22,23
10676 };
10677
10678 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10679 {
10680         int i, j;
10681         cl_locnode_t *loc = (cl_locnode_t *)ent;
10682         vec3_t mins, size;
10683         float vertex3f[6*4*3];
10684         CHECKGLERROR
10685         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10686         GL_DepthMask(false);
10687         GL_DepthRange(0, 1);
10688         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10689         GL_DepthTest(true);
10690         GL_CullFace(GL_NONE);
10691         R_EntityMatrix(&identitymatrix);
10692
10693 //      R_Mesh_ResetTextureState();
10694
10695         i = surfacelist[0];
10696         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10697                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10698                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10699                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10700
10701         if (VectorCompare(loc->mins, loc->maxs))
10702         {
10703                 VectorSet(size, 2, 2, 2);
10704                 VectorMA(loc->mins, -0.5f, size, mins);
10705         }
10706         else
10707         {
10708                 VectorCopy(loc->mins, mins);
10709                 VectorSubtract(loc->maxs, loc->mins, size);
10710         }
10711
10712         for (i = 0;i < 6*4*3;)
10713                 for (j = 0;j < 3;j++, i++)
10714                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10715
10716         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10717         R_SetupShader_Generic_NoTexture(false, false);
10718         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10719 }
10720
10721 void R_DrawLocs(void)
10722 {
10723         int index;
10724         cl_locnode_t *loc, *nearestloc;
10725         vec3_t center;
10726         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10727         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10728         {
10729                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10730                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10731         }
10732 }
10733
10734 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10735 {
10736         if (decalsystem->decals)
10737                 Mem_Free(decalsystem->decals);
10738         memset(decalsystem, 0, sizeof(*decalsystem));
10739 }
10740
10741 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)
10742 {
10743         tridecal_t *decal;
10744         tridecal_t *decals;
10745         int i;
10746
10747         // expand or initialize the system
10748         if (decalsystem->maxdecals <= decalsystem->numdecals)
10749         {
10750                 decalsystem_t old = *decalsystem;
10751                 qboolean useshortelements;
10752                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10753                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10754                 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)));
10755                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10756                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10757                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10758                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10759                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10760                 if (decalsystem->numdecals)
10761                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10762                 if (old.decals)
10763                         Mem_Free(old.decals);
10764                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10765                         decalsystem->element3i[i] = i;
10766                 if (useshortelements)
10767                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10768                                 decalsystem->element3s[i] = i;
10769         }
10770
10771         // grab a decal and search for another free slot for the next one
10772         decals = decalsystem->decals;
10773         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10774         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10775                 ;
10776         decalsystem->freedecal = i;
10777         if (decalsystem->numdecals <= i)
10778                 decalsystem->numdecals = i + 1;
10779
10780         // initialize the decal
10781         decal->lived = 0;
10782         decal->triangleindex = triangleindex;
10783         decal->surfaceindex = surfaceindex;
10784         decal->decalsequence = decalsequence;
10785         decal->color4f[0][0] = c0[0];
10786         decal->color4f[0][1] = c0[1];
10787         decal->color4f[0][2] = c0[2];
10788         decal->color4f[0][3] = 1;
10789         decal->color4f[1][0] = c1[0];
10790         decal->color4f[1][1] = c1[1];
10791         decal->color4f[1][2] = c1[2];
10792         decal->color4f[1][3] = 1;
10793         decal->color4f[2][0] = c2[0];
10794         decal->color4f[2][1] = c2[1];
10795         decal->color4f[2][2] = c2[2];
10796         decal->color4f[2][3] = 1;
10797         decal->vertex3f[0][0] = v0[0];
10798         decal->vertex3f[0][1] = v0[1];
10799         decal->vertex3f[0][2] = v0[2];
10800         decal->vertex3f[1][0] = v1[0];
10801         decal->vertex3f[1][1] = v1[1];
10802         decal->vertex3f[1][2] = v1[2];
10803         decal->vertex3f[2][0] = v2[0];
10804         decal->vertex3f[2][1] = v2[1];
10805         decal->vertex3f[2][2] = v2[2];
10806         decal->texcoord2f[0][0] = t0[0];
10807         decal->texcoord2f[0][1] = t0[1];
10808         decal->texcoord2f[1][0] = t1[0];
10809         decal->texcoord2f[1][1] = t1[1];
10810         decal->texcoord2f[2][0] = t2[0];
10811         decal->texcoord2f[2][1] = t2[1];
10812         TriangleNormal(v0, v1, v2, decal->plane);
10813         VectorNormalize(decal->plane);
10814         decal->plane[3] = DotProduct(v0, decal->plane);
10815 }
10816
10817 extern cvar_t cl_decals_bias;
10818 extern cvar_t cl_decals_models;
10819 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10820 // baseparms, parms, temps
10821 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)
10822 {
10823         int cornerindex;
10824         int index;
10825         float v[9][3];
10826         const float *vertex3f;
10827         const float *normal3f;
10828         int numpoints;
10829         float points[2][9][3];
10830         float temp[3];
10831         float tc[9][2];
10832         float f;
10833         float c[9][4];
10834         const int *e;
10835
10836         e = rsurface.modelelement3i + 3*triangleindex;
10837
10838         vertex3f = rsurface.modelvertex3f;
10839         normal3f = rsurface.modelnormal3f;
10840
10841         if (normal3f)
10842         {
10843                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10844                 {
10845                         index = 3*e[cornerindex];
10846                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10847                 }
10848         }
10849         else
10850         {
10851                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10852                 {
10853                         index = 3*e[cornerindex];
10854                         VectorCopy(vertex3f + index, v[cornerindex]);
10855                 }
10856         }
10857
10858         // cull backfaces
10859         //TriangleNormal(v[0], v[1], v[2], normal);
10860         //if (DotProduct(normal, localnormal) < 0.0f)
10861         //      continue;
10862         // clip by each of the box planes formed from the projection matrix
10863         // if anything survives, we emit the decal
10864         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]);
10865         if (numpoints < 3)
10866                 return;
10867         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]);
10868         if (numpoints < 3)
10869                 return;
10870         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]);
10871         if (numpoints < 3)
10872                 return;
10873         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]);
10874         if (numpoints < 3)
10875                 return;
10876         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]);
10877         if (numpoints < 3)
10878                 return;
10879         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]);
10880         if (numpoints < 3)
10881                 return;
10882         // some part of the triangle survived, so we have to accept it...
10883         if (dynamic)
10884         {
10885                 // dynamic always uses the original triangle
10886                 numpoints = 3;
10887                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10888                 {
10889                         index = 3*e[cornerindex];
10890                         VectorCopy(vertex3f + index, v[cornerindex]);
10891                 }
10892         }
10893         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10894         {
10895                 // convert vertex positions to texcoords
10896                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10897                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10898                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10899                 // calculate distance fade from the projection origin
10900                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10901                 f = bound(0.0f, f, 1.0f);
10902                 c[cornerindex][0] = r * f;
10903                 c[cornerindex][1] = g * f;
10904                 c[cornerindex][2] = b * f;
10905                 c[cornerindex][3] = 1.0f;
10906                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10907         }
10908         if (dynamic)
10909                 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);
10910         else
10911                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10912                         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);
10913 }
10914 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)
10915 {
10916         matrix4x4_t projection;
10917         decalsystem_t *decalsystem;
10918         qboolean dynamic;
10919         dp_model_t *model;
10920         const msurface_t *surface;
10921         const msurface_t *surfaces;
10922         const int *surfacelist;
10923         const texture_t *texture;
10924         int numtriangles;
10925         int numsurfacelist;
10926         int surfacelistindex;
10927         int surfaceindex;
10928         int triangleindex;
10929         float localorigin[3];
10930         float localnormal[3];
10931         float localmins[3];
10932         float localmaxs[3];
10933         float localsize;
10934         //float normal[3];
10935         float planes[6][4];
10936         float angles[3];
10937         bih_t *bih;
10938         int bih_triangles_count;
10939         int bih_triangles[256];
10940         int bih_surfaces[256];
10941
10942         decalsystem = &ent->decalsystem;
10943         model = ent->model;
10944         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10945         {
10946                 R_DecalSystem_Reset(&ent->decalsystem);
10947                 return;
10948         }
10949
10950         if (!model->brush.data_leafs && !cl_decals_models.integer)
10951         {
10952                 if (decalsystem->model)
10953                         R_DecalSystem_Reset(decalsystem);
10954                 return;
10955         }
10956
10957         if (decalsystem->model != model)
10958                 R_DecalSystem_Reset(decalsystem);
10959         decalsystem->model = model;
10960
10961         RSurf_ActiveModelEntity(ent, true, false, false);
10962
10963         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10964         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10965         VectorNormalize(localnormal);
10966         localsize = worldsize*rsurface.inversematrixscale;
10967         localmins[0] = localorigin[0] - localsize;
10968         localmins[1] = localorigin[1] - localsize;
10969         localmins[2] = localorigin[2] - localsize;
10970         localmaxs[0] = localorigin[0] + localsize;
10971         localmaxs[1] = localorigin[1] + localsize;
10972         localmaxs[2] = localorigin[2] + localsize;
10973
10974         //VectorCopy(localnormal, planes[4]);
10975         //VectorVectors(planes[4], planes[2], planes[0]);
10976         AnglesFromVectors(angles, localnormal, NULL, false);
10977         AngleVectors(angles, planes[0], planes[2], planes[4]);
10978         VectorNegate(planes[0], planes[1]);
10979         VectorNegate(planes[2], planes[3]);
10980         VectorNegate(planes[4], planes[5]);
10981         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10982         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10983         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10984         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10985         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10986         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10987
10988 #if 1
10989 // works
10990 {
10991         matrix4x4_t forwardprojection;
10992         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10993         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10994 }
10995 #else
10996 // broken
10997 {
10998         float projectionvector[4][3];
10999         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11000         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11001         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11002         projectionvector[0][0] = planes[0][0] * ilocalsize;
11003         projectionvector[0][1] = planes[1][0] * ilocalsize;
11004         projectionvector[0][2] = planes[2][0] * ilocalsize;
11005         projectionvector[1][0] = planes[0][1] * ilocalsize;
11006         projectionvector[1][1] = planes[1][1] * ilocalsize;
11007         projectionvector[1][2] = planes[2][1] * ilocalsize;
11008         projectionvector[2][0] = planes[0][2] * ilocalsize;
11009         projectionvector[2][1] = planes[1][2] * ilocalsize;
11010         projectionvector[2][2] = planes[2][2] * ilocalsize;
11011         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11012         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11013         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11014         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11015 }
11016 #endif
11017
11018         dynamic = model->surfmesh.isanimated;
11019         numsurfacelist = model->nummodelsurfaces;
11020         surfacelist = model->sortedmodelsurfaces;
11021         surfaces = model->data_surfaces;
11022
11023         bih = NULL;
11024         bih_triangles_count = -1;
11025         if(!dynamic)
11026         {
11027                 if(model->render_bih.numleafs)
11028                         bih = &model->render_bih;
11029                 else if(model->collision_bih.numleafs)
11030                         bih = &model->collision_bih;
11031         }
11032         if(bih)
11033                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11034         if(bih_triangles_count == 0)
11035                 return;
11036         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11037                 return;
11038         if(bih_triangles_count > 0)
11039         {
11040                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11041                 {
11042                         surfaceindex = bih_surfaces[triangleindex];
11043                         surface = surfaces + surfaceindex;
11044                         texture = surface->texture;
11045                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11046                                 continue;
11047                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11048                                 continue;
11049                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11050                 }
11051         }
11052         else
11053         {
11054                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11055                 {
11056                         surfaceindex = surfacelist[surfacelistindex];
11057                         surface = surfaces + surfaceindex;
11058                         // check cull box first because it rejects more than any other check
11059                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11060                                 continue;
11061                         // skip transparent surfaces
11062                         texture = surface->texture;
11063                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11064                                 continue;
11065                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11066                                 continue;
11067                         numtriangles = surface->num_triangles;
11068                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11069                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11070                 }
11071         }
11072 }
11073
11074 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11075 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)
11076 {
11077         int renderentityindex;
11078         float worldmins[3];
11079         float worldmaxs[3];
11080         entity_render_t *ent;
11081
11082         if (!cl_decals_newsystem.integer)
11083                 return;
11084
11085         worldmins[0] = worldorigin[0] - worldsize;
11086         worldmins[1] = worldorigin[1] - worldsize;
11087         worldmins[2] = worldorigin[2] - worldsize;
11088         worldmaxs[0] = worldorigin[0] + worldsize;
11089         worldmaxs[1] = worldorigin[1] + worldsize;
11090         worldmaxs[2] = worldorigin[2] + worldsize;
11091
11092         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11093
11094         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11095         {
11096                 ent = r_refdef.scene.entities[renderentityindex];
11097                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11098                         continue;
11099
11100                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11101         }
11102 }
11103
11104 typedef struct r_decalsystem_splatqueue_s
11105 {
11106         vec3_t worldorigin;
11107         vec3_t worldnormal;
11108         float color[4];
11109         float tcrange[4];
11110         float worldsize;
11111         int decalsequence;
11112 }
11113 r_decalsystem_splatqueue_t;
11114
11115 int r_decalsystem_numqueued = 0;
11116 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11117
11118 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)
11119 {
11120         r_decalsystem_splatqueue_t *queue;
11121
11122         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11123                 return;
11124
11125         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11126         VectorCopy(worldorigin, queue->worldorigin);
11127         VectorCopy(worldnormal, queue->worldnormal);
11128         Vector4Set(queue->color, r, g, b, a);
11129         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11130         queue->worldsize = worldsize;
11131         queue->decalsequence = cl.decalsequence++;
11132 }
11133
11134 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11135 {
11136         int i;
11137         r_decalsystem_splatqueue_t *queue;
11138
11139         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11140                 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);
11141         r_decalsystem_numqueued = 0;
11142 }
11143
11144 extern cvar_t cl_decals_max;
11145 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11146 {
11147         int i;
11148         decalsystem_t *decalsystem = &ent->decalsystem;
11149         int numdecals;
11150         int killsequence;
11151         tridecal_t *decal;
11152         float frametime;
11153         float lifetime;
11154
11155         if (!decalsystem->numdecals)
11156                 return;
11157
11158         if (r_showsurfaces.integer)
11159                 return;
11160
11161         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11162         {
11163                 R_DecalSystem_Reset(decalsystem);
11164                 return;
11165         }
11166
11167         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11168         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11169
11170         if (decalsystem->lastupdatetime)
11171                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11172         else
11173                 frametime = 0;
11174         decalsystem->lastupdatetime = r_refdef.scene.time;
11175         decal = decalsystem->decals;
11176         numdecals = decalsystem->numdecals;
11177
11178         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11179         {
11180                 if (decal->color4f[0][3])
11181                 {
11182                         decal->lived += frametime;
11183                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11184                         {
11185                                 memset(decal, 0, sizeof(*decal));
11186                                 if (decalsystem->freedecal > i)
11187                                         decalsystem->freedecal = i;
11188                         }
11189                 }
11190         }
11191         decal = decalsystem->decals;
11192         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11193                 numdecals--;
11194
11195         // collapse the array by shuffling the tail decals into the gaps
11196         for (;;)
11197         {
11198                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11199                         decalsystem->freedecal++;
11200                 if (decalsystem->freedecal == numdecals)
11201                         break;
11202                 decal[decalsystem->freedecal] = decal[--numdecals];
11203         }
11204
11205         decalsystem->numdecals = numdecals;
11206
11207         if (numdecals <= 0)
11208         {
11209                 // if there are no decals left, reset decalsystem
11210                 R_DecalSystem_Reset(decalsystem);
11211         }
11212 }
11213
11214 extern skinframe_t *decalskinframe;
11215 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11216 {
11217         int i;
11218         decalsystem_t *decalsystem = &ent->decalsystem;
11219         int numdecals;
11220         tridecal_t *decal;
11221         float faderate;
11222         float alpha;
11223         float *v3f;
11224         float *c4f;
11225         float *t2f;
11226         const int *e;
11227         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11228         int numtris = 0;
11229
11230         numdecals = decalsystem->numdecals;
11231         if (!numdecals)
11232                 return;
11233
11234         if (r_showsurfaces.integer)
11235                 return;
11236
11237         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11238         {
11239                 R_DecalSystem_Reset(decalsystem);
11240                 return;
11241         }
11242
11243         // if the model is static it doesn't matter what value we give for
11244         // wantnormals and wanttangents, so this logic uses only rules applicable
11245         // to a model, knowing that they are meaningless otherwise
11246         if (ent == r_refdef.scene.worldentity)
11247                 RSurf_ActiveWorldEntity();
11248         else
11249                 RSurf_ActiveModelEntity(ent, false, false, false);
11250
11251         decalsystem->lastupdatetime = r_refdef.scene.time;
11252         decal = decalsystem->decals;
11253
11254         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11255
11256         // update vertex positions for animated models
11257         v3f = decalsystem->vertex3f;
11258         c4f = decalsystem->color4f;
11259         t2f = decalsystem->texcoord2f;
11260         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11261         {
11262                 if (!decal->color4f[0][3])
11263                         continue;
11264
11265                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11266                         continue;
11267
11268                 // skip backfaces
11269                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11270                         continue;
11271
11272                 // update color values for fading decals
11273                 if (decal->lived >= cl_decals_time.value)
11274                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11275                 else
11276                         alpha = 1.0f;
11277
11278                 c4f[ 0] = decal->color4f[0][0] * alpha;
11279                 c4f[ 1] = decal->color4f[0][1] * alpha;
11280                 c4f[ 2] = decal->color4f[0][2] * alpha;
11281                 c4f[ 3] = 1;
11282                 c4f[ 4] = decal->color4f[1][0] * alpha;
11283                 c4f[ 5] = decal->color4f[1][1] * alpha;
11284                 c4f[ 6] = decal->color4f[1][2] * alpha;
11285                 c4f[ 7] = 1;
11286                 c4f[ 8] = decal->color4f[2][0] * alpha;
11287                 c4f[ 9] = decal->color4f[2][1] * alpha;
11288                 c4f[10] = decal->color4f[2][2] * alpha;
11289                 c4f[11] = 1;
11290
11291                 t2f[0] = decal->texcoord2f[0][0];
11292                 t2f[1] = decal->texcoord2f[0][1];
11293                 t2f[2] = decal->texcoord2f[1][0];
11294                 t2f[3] = decal->texcoord2f[1][1];
11295                 t2f[4] = decal->texcoord2f[2][0];
11296                 t2f[5] = decal->texcoord2f[2][1];
11297
11298                 // update vertex positions for animated models
11299                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11300                 {
11301                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11302                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11303                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11304                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11305                 }
11306                 else
11307                 {
11308                         VectorCopy(decal->vertex3f[0], v3f);
11309                         VectorCopy(decal->vertex3f[1], v3f + 3);
11310                         VectorCopy(decal->vertex3f[2], v3f + 6);
11311                 }
11312
11313                 if (r_refdef.fogenabled)
11314                 {
11315                         alpha = RSurf_FogVertex(v3f);
11316                         VectorScale(c4f, alpha, c4f);
11317                         alpha = RSurf_FogVertex(v3f + 3);
11318                         VectorScale(c4f + 4, alpha, c4f + 4);
11319                         alpha = RSurf_FogVertex(v3f + 6);
11320                         VectorScale(c4f + 8, alpha, c4f + 8);
11321                 }
11322
11323                 v3f += 9;
11324                 c4f += 12;
11325                 t2f += 6;
11326                 numtris++;
11327         }
11328
11329         if (numtris > 0)
11330         {
11331                 r_refdef.stats.drawndecals += numtris;
11332
11333                 // now render the decals all at once
11334                 // (this assumes they all use one particle font texture!)
11335                 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);
11336 //              R_Mesh_ResetTextureState();
11337                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11338                 GL_DepthMask(false);
11339                 GL_DepthRange(0, 1);
11340                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11341                 GL_DepthTest(true);
11342                 GL_CullFace(GL_NONE);
11343                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11344                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11345                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11346         }
11347 }
11348
11349 static void R_DrawModelDecals(void)
11350 {
11351         int i, numdecals;
11352
11353         // fade faster when there are too many decals
11354         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11355         for (i = 0;i < r_refdef.scene.numentities;i++)
11356                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11357
11358         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11359         for (i = 0;i < r_refdef.scene.numentities;i++)
11360                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11361                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11362
11363         R_DecalSystem_ApplySplatEntitiesQueue();
11364
11365         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11366         for (i = 0;i < r_refdef.scene.numentities;i++)
11367                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11368
11369         r_refdef.stats.totaldecals += numdecals;
11370
11371         if (r_showsurfaces.integer)
11372                 return;
11373
11374         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11375
11376         for (i = 0;i < r_refdef.scene.numentities;i++)
11377         {
11378                 if (!r_refdef.viewcache.entityvisible[i])
11379                         continue;
11380                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11381                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11382         }
11383 }
11384
11385 extern cvar_t mod_collision_bih;
11386 static void R_DrawDebugModel(void)
11387 {
11388         entity_render_t *ent = rsurface.entity;
11389         int i, j, k, l, flagsmask;
11390         const msurface_t *surface;
11391         dp_model_t *model = ent->model;
11392         vec3_t v;
11393
11394         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11395                 return;
11396
11397         if (r_showoverdraw.value > 0)
11398         {
11399                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11400                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11401                 R_SetupShader_Generic_NoTexture(false, false);
11402                 GL_DepthTest(false);
11403                 GL_DepthMask(false);
11404                 GL_DepthRange(0, 1);
11405                 GL_BlendFunc(GL_ONE, GL_ONE);
11406                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11407                 {
11408                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11409                                 continue;
11410                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11411                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11412                         {
11413                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11414                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11415                                 if (!rsurface.texture->currentlayers->depthmask)
11416                                         GL_Color(c, 0, 0, 1.0f);
11417                                 else if (ent == r_refdef.scene.worldentity)
11418                                         GL_Color(c, c, c, 1.0f);
11419                                 else
11420                                         GL_Color(0, c, 0, 1.0f);
11421                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11422                                 RSurf_DrawBatch();
11423                         }
11424                 }
11425                 rsurface.texture = NULL;
11426         }
11427
11428         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11429
11430 //      R_Mesh_ResetTextureState();
11431         R_SetupShader_Generic_NoTexture(false, false);
11432         GL_DepthRange(0, 1);
11433         GL_DepthTest(!r_showdisabledepthtest.integer);
11434         GL_DepthMask(false);
11435         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11436
11437         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11438         {
11439                 int triangleindex;
11440                 int bihleafindex;
11441                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11442                 const q3mbrush_t *brush;
11443                 const bih_t *bih = &model->collision_bih;
11444                 const bih_leaf_t *bihleaf;
11445                 float vertex3f[3][3];
11446                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11447                 cullbox = false;
11448                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11449                 {
11450                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11451                                 continue;
11452                         switch (bihleaf->type)
11453                         {
11454                         case BIH_BRUSH:
11455                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11456                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11457                                 {
11458                                         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);
11459                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11460                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11461                                 }
11462                                 break;
11463                         case BIH_COLLISIONTRIANGLE:
11464                                 triangleindex = bihleaf->itemindex;
11465                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11466                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11467                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11468                                 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);
11469                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11470                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11471                                 break;
11472                         case BIH_RENDERTRIANGLE:
11473                                 triangleindex = bihleaf->itemindex;
11474                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11475                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11476                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11477                                 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);
11478                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11479                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11480                                 break;
11481                         }
11482                 }
11483         }
11484
11485         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11486
11487 #ifndef USE_GLES2
11488         if (r_showtris.integer && qglPolygonMode)
11489         {
11490                 if (r_showdisabledepthtest.integer)
11491                 {
11492                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11493                         GL_DepthMask(false);
11494                 }
11495                 else
11496                 {
11497                         GL_BlendFunc(GL_ONE, GL_ZERO);
11498                         GL_DepthMask(true);
11499                 }
11500                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11501                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11502                 {
11503                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11504                                 continue;
11505                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11506                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11507                         {
11508                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11509                                 if (!rsurface.texture->currentlayers->depthmask)
11510                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11511                                 else if (ent == r_refdef.scene.worldentity)
11512                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11513                                 else
11514                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11515                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11516                                 RSurf_DrawBatch();
11517                         }
11518                 }
11519                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11520                 rsurface.texture = NULL;
11521         }
11522
11523         if (r_shownormals.value != 0 && qglBegin)
11524         {
11525                 if (r_showdisabledepthtest.integer)
11526                 {
11527                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11528                         GL_DepthMask(false);
11529                 }
11530                 else
11531                 {
11532                         GL_BlendFunc(GL_ONE, GL_ZERO);
11533                         GL_DepthMask(true);
11534                 }
11535                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11536                 {
11537                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11538                                 continue;
11539                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11540                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11541                         {
11542                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11543                                 qglBegin(GL_LINES);
11544                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11545                                 {
11546                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11547                                         {
11548                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11549                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11550                                                 qglVertex3f(v[0], v[1], v[2]);
11551                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11552                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11553                                                 qglVertex3f(v[0], v[1], v[2]);
11554                                         }
11555                                 }
11556                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11557                                 {
11558                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11559                                         {
11560                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11561                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11562                                                 qglVertex3f(v[0], v[1], v[2]);
11563                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11564                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11565                                                 qglVertex3f(v[0], v[1], v[2]);
11566                                         }
11567                                 }
11568                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11569                                 {
11570                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11571                                         {
11572                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11573                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11574                                                 qglVertex3f(v[0], v[1], v[2]);
11575                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11576                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11577                                                 qglVertex3f(v[0], v[1], v[2]);
11578                                         }
11579                                 }
11580                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11581                                 {
11582                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11583                                         {
11584                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11585                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11586                                                 qglVertex3f(v[0], v[1], v[2]);
11587                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11588                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11589                                                 qglVertex3f(v[0], v[1], v[2]);
11590                                         }
11591                                 }
11592                                 qglEnd();
11593                                 CHECKGLERROR
11594                         }
11595                 }
11596                 rsurface.texture = NULL;
11597         }
11598 #endif
11599 }
11600
11601 int r_maxsurfacelist = 0;
11602 const msurface_t **r_surfacelist = NULL;
11603 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11604 {
11605         int i, j, endj, flagsmask;
11606         dp_model_t *model = r_refdef.scene.worldmodel;
11607         msurface_t *surfaces;
11608         unsigned char *update;
11609         int numsurfacelist = 0;
11610         if (model == NULL)
11611                 return;
11612
11613         if (r_maxsurfacelist < model->num_surfaces)
11614         {
11615                 r_maxsurfacelist = model->num_surfaces;
11616                 if (r_surfacelist)
11617                         Mem_Free((msurface_t**)r_surfacelist);
11618                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11619         }
11620
11621         RSurf_ActiveWorldEntity();
11622
11623         surfaces = model->data_surfaces;
11624         update = model->brushq1.lightmapupdateflags;
11625
11626         // update light styles on this submodel
11627         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11628         {
11629                 model_brush_lightstyleinfo_t *style;
11630                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11631                 {
11632                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11633                         {
11634                                 int *list = style->surfacelist;
11635                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11636                                 for (j = 0;j < style->numsurfaces;j++)
11637                                         update[list[j]] = true;
11638                         }
11639                 }
11640         }
11641
11642         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11643
11644         if (debug)
11645         {
11646                 R_DrawDebugModel();
11647                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11648                 return;
11649         }
11650
11651         rsurface.lightmaptexture = NULL;
11652         rsurface.deluxemaptexture = NULL;
11653         rsurface.uselightmaptexture = false;
11654         rsurface.texture = NULL;
11655         rsurface.rtlight = NULL;
11656         numsurfacelist = 0;
11657         // add visible surfaces to draw list
11658         for (i = 0;i < model->nummodelsurfaces;i++)
11659         {
11660                 j = model->sortedmodelsurfaces[i];
11661                 if (r_refdef.viewcache.world_surfacevisible[j])
11662                         r_surfacelist[numsurfacelist++] = surfaces + j;
11663         }
11664         // update lightmaps if needed
11665         if (model->brushq1.firstrender)
11666         {
11667                 model->brushq1.firstrender = false;
11668                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11669                         if (update[j])
11670                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11671         }
11672         else if (update)
11673         {
11674                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11675                         if (r_refdef.viewcache.world_surfacevisible[j])
11676                                 if (update[j])
11677                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11678         }
11679         // don't do anything if there were no surfaces
11680         if (!numsurfacelist)
11681         {
11682                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11683                 return;
11684         }
11685         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11686
11687         // add to stats if desired
11688         if (r_speeds.integer && !skysurfaces && !depthonly)
11689         {
11690                 r_refdef.stats.world_surfaces += numsurfacelist;
11691                 for (j = 0;j < numsurfacelist;j++)
11692                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11693         }
11694
11695         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11696 }
11697
11698 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11699 {
11700         int i, j, endj, flagsmask;
11701         dp_model_t *model = ent->model;
11702         msurface_t *surfaces;
11703         unsigned char *update;
11704         int numsurfacelist = 0;
11705         if (model == NULL)
11706                 return;
11707
11708         if (r_maxsurfacelist < model->num_surfaces)
11709         {
11710                 r_maxsurfacelist = model->num_surfaces;
11711                 if (r_surfacelist)
11712                         Mem_Free((msurface_t **)r_surfacelist);
11713                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11714         }
11715
11716         // if the model is static it doesn't matter what value we give for
11717         // wantnormals and wanttangents, so this logic uses only rules applicable
11718         // to a model, knowing that they are meaningless otherwise
11719         if (ent == r_refdef.scene.worldentity)
11720                 RSurf_ActiveWorldEntity();
11721         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11722                 RSurf_ActiveModelEntity(ent, false, false, false);
11723         else if (prepass)
11724                 RSurf_ActiveModelEntity(ent, true, true, true);
11725         else if (depthonly)
11726         {
11727                 switch (vid.renderpath)
11728                 {
11729                 case RENDERPATH_GL20:
11730                 case RENDERPATH_D3D9:
11731                 case RENDERPATH_D3D10:
11732                 case RENDERPATH_D3D11:
11733                 case RENDERPATH_SOFT:
11734                 case RENDERPATH_GLES2:
11735                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11736                         break;
11737                 case RENDERPATH_GL11:
11738                 case RENDERPATH_GL13:
11739                 case RENDERPATH_GLES1:
11740                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11741                         break;
11742                 }
11743         }
11744         else
11745         {
11746                 switch (vid.renderpath)
11747                 {
11748                 case RENDERPATH_GL20:
11749                 case RENDERPATH_D3D9:
11750                 case RENDERPATH_D3D10:
11751                 case RENDERPATH_D3D11:
11752                 case RENDERPATH_SOFT:
11753                 case RENDERPATH_GLES2:
11754                         RSurf_ActiveModelEntity(ent, true, true, false);
11755                         break;
11756                 case RENDERPATH_GL11:
11757                 case RENDERPATH_GL13:
11758                 case RENDERPATH_GLES1:
11759                         RSurf_ActiveModelEntity(ent, true, false, false);
11760                         break;
11761                 }
11762         }
11763
11764         surfaces = model->data_surfaces;
11765         update = model->brushq1.lightmapupdateflags;
11766
11767         // update light styles
11768         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11769         {
11770                 model_brush_lightstyleinfo_t *style;
11771                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11772                 {
11773                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11774                         {
11775                                 int *list = style->surfacelist;
11776                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11777                                 for (j = 0;j < style->numsurfaces;j++)
11778                                         update[list[j]] = true;
11779                         }
11780                 }
11781         }
11782
11783         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11784
11785         if (debug)
11786         {
11787                 R_DrawDebugModel();
11788                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11789                 return;
11790         }
11791
11792         rsurface.lightmaptexture = NULL;
11793         rsurface.deluxemaptexture = NULL;
11794         rsurface.uselightmaptexture = false;
11795         rsurface.texture = NULL;
11796         rsurface.rtlight = NULL;
11797         numsurfacelist = 0;
11798         // add visible surfaces to draw list
11799         for (i = 0;i < model->nummodelsurfaces;i++)
11800                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11801         // don't do anything if there were no surfaces
11802         if (!numsurfacelist)
11803         {
11804                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11805                 return;
11806         }
11807         // update lightmaps if needed
11808         if (update)
11809         {
11810                 int updated = 0;
11811                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11812                 {
11813                         if (update[j])
11814                         {
11815                                 updated++;
11816                                 R_BuildLightMap(ent, surfaces + j);
11817                         }
11818                 }
11819         }
11820
11821         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11822
11823         // add to stats if desired
11824         if (r_speeds.integer && !skysurfaces && !depthonly)
11825         {
11826                 r_refdef.stats.entities_surfaces += numsurfacelist;
11827                 for (j = 0;j < numsurfacelist;j++)
11828                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11829         }
11830
11831         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11832 }
11833
11834 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11835 {
11836         static texture_t texture;
11837         static msurface_t surface;
11838         const msurface_t *surfacelist = &surface;
11839
11840         // fake enough texture and surface state to render this geometry
11841
11842         texture.update_lastrenderframe = -1; // regenerate this texture
11843         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11844         texture.currentskinframe = skinframe;
11845         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11846         texture.offsetmapping = OFFSETMAPPING_OFF;
11847         texture.offsetscale = 1;
11848         texture.specularscalemod = 1;
11849         texture.specularpowermod = 1;
11850
11851         surface.texture = &texture;
11852         surface.num_triangles = numtriangles;
11853         surface.num_firsttriangle = firsttriangle;
11854         surface.num_vertices = numvertices;
11855         surface.num_firstvertex = firstvertex;
11856
11857         // now render it
11858         rsurface.texture = R_GetCurrentTexture(surface.texture);
11859         rsurface.lightmaptexture = NULL;
11860         rsurface.deluxemaptexture = NULL;
11861         rsurface.uselightmaptexture = false;
11862         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11863 }
11864
11865 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)
11866 {
11867         static msurface_t surface;
11868         const msurface_t *surfacelist = &surface;
11869
11870         // fake enough texture and surface state to render this geometry
11871         surface.texture = texture;
11872         surface.num_triangles = numtriangles;
11873         surface.num_firsttriangle = firsttriangle;
11874         surface.num_vertices = numvertices;
11875         surface.num_firstvertex = firstvertex;
11876
11877         // now render it
11878         rsurface.texture = R_GetCurrentTexture(surface.texture);
11879         rsurface.lightmaptexture = NULL;
11880         rsurface.deluxemaptexture = NULL;
11881         rsurface.uselightmaptexture = false;
11882         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11883 }