]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix typos
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
88 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
91 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
92 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
101 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
125 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
135 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading"};
136 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred)"};
137
138 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
139 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
140 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
141 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
142 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
143 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
144 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
145 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
146
147 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)"};
148 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"};
149
150 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
151 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
152 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
153
154 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"};
155 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"};
156 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"};
157 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
158 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
159 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"};
160 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)"};
161 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)"};
162 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
163
164 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)"};
165 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
166 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)"};
167 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
168 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)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
171 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"};
172 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."};
173 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182
183 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)"};
184 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
185 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"};
186 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
187 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
188 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
189 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"};
190 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"};
191 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)"};
192
193 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
194 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
195 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
196 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
197
198 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
199 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
200
201 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
202 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
203 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
204 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
205 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
206
207 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
208 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
209 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
210 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
211 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
212 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
213 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
214 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
215 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
216 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
217
218 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"};
219
220 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"};
221
222 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
223
224 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
225
226 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
227 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"};
228
229 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."};
230
231 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)"};
232
233 extern cvar_t v_glslgamma;
234 extern cvar_t v_glslgamma_2d;
235
236 extern qboolean v_flipped_state;
237
238 r_framebufferstate_t r_fb;
239
240 /// shadow volume bsp struct with automatically growing nodes buffer
241 svbsp_t r_svbsp;
242
243 rtexture_t *r_texture_blanknormalmap;
244 rtexture_t *r_texture_white;
245 rtexture_t *r_texture_grey128;
246 rtexture_t *r_texture_black;
247 rtexture_t *r_texture_notexture;
248 rtexture_t *r_texture_whitecube;
249 rtexture_t *r_texture_normalizationcube;
250 rtexture_t *r_texture_fogattenuation;
251 rtexture_t *r_texture_fogheighttexture;
252 rtexture_t *r_texture_gammaramps;
253 unsigned int r_texture_gammaramps_serial;
254 //rtexture_t *r_texture_fogintensity;
255 rtexture_t *r_texture_reflectcube;
256
257 // TODO: hash lookups?
258 typedef struct cubemapinfo_s
259 {
260         char basename[64];
261         rtexture_t *texture;
262 }
263 cubemapinfo_t;
264
265 int r_texture_numcubemaps;
266 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
267
268 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
269 unsigned int r_numqueries;
270 unsigned int r_maxqueries;
271
272 typedef struct r_qwskincache_s
273 {
274         char name[MAX_QPATH];
275         skinframe_t *skinframe;
276 }
277 r_qwskincache_t;
278
279 static r_qwskincache_t *r_qwskincache;
280 static int r_qwskincache_size;
281
282 /// vertex coordinates for a quad that covers the screen exactly
283 extern const float r_screenvertex3f[12];
284 extern const float r_d3dscreenvertex3f[12];
285 const float r_screenvertex3f[12] =
286 {
287         0, 0, 0,
288         1, 0, 0,
289         1, 1, 0,
290         0, 1, 0
291 };
292 const float r_d3dscreenvertex3f[12] =
293 {
294         0, 1, 0,
295         1, 1, 0,
296         1, 0, 0,
297         0, 0, 0
298 };
299
300 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
301 {
302         int i;
303         for (i = 0;i < verts;i++)
304         {
305                 out[0] = in[0] * r;
306                 out[1] = in[1] * g;
307                 out[2] = in[2] * b;
308                 out[3] = in[3];
309                 in += 4;
310                 out += 4;
311         }
312 }
313
314 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
315 {
316         int i;
317         for (i = 0;i < verts;i++)
318         {
319                 out[0] = r;
320                 out[1] = g;
321                 out[2] = b;
322                 out[3] = a;
323                 out += 4;
324         }
325 }
326
327 // FIXME: move this to client?
328 void FOG_clear(void)
329 {
330         if (gamemode == GAME_NEHAHRA)
331         {
332                 Cvar_Set("gl_fogenable", "0");
333                 Cvar_Set("gl_fogdensity", "0.2");
334                 Cvar_Set("gl_fogred", "0.3");
335                 Cvar_Set("gl_foggreen", "0.3");
336                 Cvar_Set("gl_fogblue", "0.3");
337         }
338         r_refdef.fog_density = 0;
339         r_refdef.fog_red = 0;
340         r_refdef.fog_green = 0;
341         r_refdef.fog_blue = 0;
342         r_refdef.fog_alpha = 1;
343         r_refdef.fog_start = 0;
344         r_refdef.fog_end = 16384;
345         r_refdef.fog_height = 1<<30;
346         r_refdef.fog_fadedepth = 128;
347         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
348 }
349
350 static void R_BuildBlankTextures(void)
351 {
352         unsigned char data[4];
353         data[2] = 128; // normal X
354         data[1] = 128; // normal Y
355         data[0] = 255; // normal Z
356         data[3] = 255; // height
357         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 255;
359         data[1] = 255;
360         data[2] = 255;
361         data[3] = 255;
362         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 128;
364         data[1] = 128;
365         data[2] = 128;
366         data[3] = 255;
367         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368         data[0] = 0;
369         data[1] = 0;
370         data[2] = 0;
371         data[3] = 255;
372         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
373 }
374
375 static void R_BuildNoTexture(void)
376 {
377         int x, y;
378         unsigned char pix[16][16][4];
379         // this makes a light grey/dark grey checkerboard texture
380         for (y = 0;y < 16;y++)
381         {
382                 for (x = 0;x < 16;x++)
383                 {
384                         if ((y < 8) ^ (x < 8))
385                         {
386                                 pix[y][x][0] = 128;
387                                 pix[y][x][1] = 128;
388                                 pix[y][x][2] = 128;
389                                 pix[y][x][3] = 255;
390                         }
391                         else
392                         {
393                                 pix[y][x][0] = 64;
394                                 pix[y][x][1] = 64;
395                                 pix[y][x][2] = 64;
396                                 pix[y][x][3] = 255;
397                         }
398                 }
399         }
400         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
401 }
402
403 static void R_BuildWhiteCube(void)
404 {
405         unsigned char data[6*1*1*4];
406         memset(data, 255, sizeof(data));
407         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildNormalizationCube(void)
411 {
412         int x, y, side;
413         vec3_t v;
414         vec_t s, t, intensity;
415 #define NORMSIZE 64
416         unsigned char *data;
417         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
418         for (side = 0;side < 6;side++)
419         {
420                 for (y = 0;y < NORMSIZE;y++)
421                 {
422                         for (x = 0;x < NORMSIZE;x++)
423                         {
424                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426                                 switch(side)
427                                 {
428                                 default:
429                                 case 0:
430                                         v[0] = 1;
431                                         v[1] = -t;
432                                         v[2] = -s;
433                                         break;
434                                 case 1:
435                                         v[0] = -1;
436                                         v[1] = -t;
437                                         v[2] = s;
438                                         break;
439                                 case 2:
440                                         v[0] = s;
441                                         v[1] = 1;
442                                         v[2] = t;
443                                         break;
444                                 case 3:
445                                         v[0] = s;
446                                         v[1] = -1;
447                                         v[2] = -t;
448                                         break;
449                                 case 4:
450                                         v[0] = s;
451                                         v[1] = -t;
452                                         v[2] = 1;
453                                         break;
454                                 case 5:
455                                         v[0] = -s;
456                                         v[1] = -t;
457                                         v[2] = -1;
458                                         break;
459                                 }
460                                 intensity = 127.0f / sqrt(DotProduct(v, v));
461                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
462                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
463                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
464                                 data[((side*64+y)*64+x)*4+3] = 255;
465                         }
466                 }
467         }
468         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469         Mem_Free(data);
470 }
471
472 static void R_BuildFogTexture(void)
473 {
474         int x, b;
475 #define FOGWIDTH 256
476         unsigned char data1[FOGWIDTH][4];
477         //unsigned char data2[FOGWIDTH][4];
478         double d, r, alpha;
479
480         r_refdef.fogmasktable_start = r_refdef.fog_start;
481         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
482         r_refdef.fogmasktable_range = r_refdef.fogrange;
483         r_refdef.fogmasktable_density = r_refdef.fog_density;
484
485         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
486         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
487         {
488                 d = (x * r - r_refdef.fogmasktable_start);
489                 if(developer_extra.integer)
490                         Con_DPrintf("%f ", d);
491                 d = max(0, d);
492                 if (r_fog_exp2.integer)
493                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
494                 else
495                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
496                 if(developer_extra.integer)
497                         Con_DPrintf(" : %f ", alpha);
498                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
499                 if(developer_extra.integer)
500                         Con_DPrintf(" = %f\n", alpha);
501                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
502         }
503
504         for (x = 0;x < FOGWIDTH;x++)
505         {
506                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
507                 data1[x][0] = b;
508                 data1[x][1] = b;
509                 data1[x][2] = b;
510                 data1[x][3] = 255;
511                 //data2[x][0] = 255 - b;
512                 //data2[x][1] = 255 - b;
513                 //data2[x][2] = 255 - b;
514                 //data2[x][3] = 255;
515         }
516         if (r_texture_fogattenuation)
517         {
518                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520         }
521         else
522         {
523                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
524                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525         }
526 }
527
528 static void R_BuildFogHeightTexture(void)
529 {
530         unsigned char *inpixels;
531         int size;
532         int x;
533         int y;
534         int j;
535         float c[4];
536         float f;
537         inpixels = NULL;
538         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
539         if (r_refdef.fogheighttexturename[0])
540                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
541         if (!inpixels)
542         {
543                 r_refdef.fog_height_tablesize = 0;
544                 if (r_texture_fogheighttexture)
545                         R_FreeTexture(r_texture_fogheighttexture);
546                 r_texture_fogheighttexture = NULL;
547                 if (r_refdef.fog_height_table2d)
548                         Mem_Free(r_refdef.fog_height_table2d);
549                 r_refdef.fog_height_table2d = NULL;
550                 if (r_refdef.fog_height_table1d)
551                         Mem_Free(r_refdef.fog_height_table1d);
552                 r_refdef.fog_height_table1d = NULL;
553                 return;
554         }
555         size = image_width;
556         r_refdef.fog_height_tablesize = size;
557         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
558         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
559         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
560         Mem_Free(inpixels);
561         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
562         // average fog color table accounting for every fog layer between a point
563         // and the camera.  (Note: attenuation is handled separately!)
564         for (y = 0;y < size;y++)
565         {
566                 for (x = 0;x < size;x++)
567                 {
568                         Vector4Clear(c);
569                         f = 0;
570                         if (x < y)
571                         {
572                                 for (j = x;j <= y;j++)
573                                 {
574                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
575                                         f++;
576                                 }
577                         }
578                         else
579                         {
580                                 for (j = x;j >= y;j--)
581                                 {
582                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
583                                         f++;
584                                 }
585                         }
586                         f = 1.0f / f;
587                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
591                 }
592         }
593         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
594 }
595
596 //=======================================================================================================================================================
597
598 static const char *builtinshaderstring =
599 #include "shader_glsl.h"
600 ;
601
602 const char *builtinhlslshaderstring =
603 #include "shader_hlsl.h"
604 ;
605
606 char *glslshaderstring = NULL;
607 char *hlslshaderstring = NULL;
608
609 //=======================================================================================================================================================
610
611 typedef struct shaderpermutationinfo_s
612 {
613         const char *pretext;
614         const char *name;
615 }
616 shaderpermutationinfo_t;
617
618 typedef struct shadermodeinfo_s
619 {
620         const char *vertexfilename;
621         const char *geometryfilename;
622         const char *fragmentfilename;
623         const char *pretext;
624         const char *name;
625 }
626 shadermodeinfo_t;
627
628 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
629 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
630 {
631         {"#define USEDIFFUSE\n", " diffuse"},
632         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
633         {"#define USEVIEWTINT\n", " viewtint"},
634         {"#define USECOLORMAPPING\n", " colormapping"},
635         {"#define USESATURATION\n", " saturation"},
636         {"#define USEFOGINSIDE\n", " foginside"},
637         {"#define USEFOGOUTSIDE\n", " fogoutside"},
638         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
639         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
640         {"#define USEGAMMARAMPS\n", " gammaramps"},
641         {"#define USECUBEFILTER\n", " cubefilter"},
642         {"#define USEGLOW\n", " glow"},
643         {"#define USEBLOOM\n", " bloom"},
644         {"#define USESPECULAR\n", " specular"},
645         {"#define USEPOSTPROCESSING\n", " postprocessing"},
646         {"#define USEREFLECTION\n", " reflection"},
647         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
648         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
649         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
650         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
651         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
652         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
653         {"#define USEALPHAKILL\n", " alphakill"},
654         {"#define USEREFLECTCUBE\n", " reflectcube"},
655         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
656         {"#define USEBOUNCEGRID\n", " bouncegrid"},
657         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
658         {"#define USETRIPPY\n", " trippy"},
659         {"#define USEDEPTHRGB\n", " depthrgb"},
660         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
661 };
662
663 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
664 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
665 {
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
684 };
685
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 struct r_glsl_permutation_s;
709 typedef struct r_glsl_permutation_s
710 {
711         /// hash lookup data
712         struct r_glsl_permutation_s *hashnext;
713         unsigned int mode;
714         unsigned int permutation;
715
716         /// indicates if we have tried compiling this permutation already
717         qboolean compiled;
718         /// 0 if compilation failed
719         int program;
720         // texture units assigned to each detected uniform
721         int tex_Texture_First;
722         int tex_Texture_Second;
723         int tex_Texture_GammaRamps;
724         int tex_Texture_Normal;
725         int tex_Texture_Color;
726         int tex_Texture_Gloss;
727         int tex_Texture_Glow;
728         int tex_Texture_SecondaryNormal;
729         int tex_Texture_SecondaryColor;
730         int tex_Texture_SecondaryGloss;
731         int tex_Texture_SecondaryGlow;
732         int tex_Texture_Pants;
733         int tex_Texture_Shirt;
734         int tex_Texture_FogHeightTexture;
735         int tex_Texture_FogMask;
736         int tex_Texture_Lightmap;
737         int tex_Texture_Deluxemap;
738         int tex_Texture_Attenuation;
739         int tex_Texture_Cube;
740         int tex_Texture_Refraction;
741         int tex_Texture_Reflection;
742         int tex_Texture_ShadowMap2D;
743         int tex_Texture_CubeProjection;
744         int tex_Texture_ScreenNormalMap;
745         int tex_Texture_ScreenDiffuse;
746         int tex_Texture_ScreenSpecular;
747         int tex_Texture_ReflectMask;
748         int tex_Texture_ReflectCube;
749         int tex_Texture_BounceGrid;
750         /// locations of detected uniforms in program object, or -1 if not found
751         int loc_Texture_First;
752         int loc_Texture_Second;
753         int loc_Texture_GammaRamps;
754         int loc_Texture_Normal;
755         int loc_Texture_Color;
756         int loc_Texture_Gloss;
757         int loc_Texture_Glow;
758         int loc_Texture_SecondaryNormal;
759         int loc_Texture_SecondaryColor;
760         int loc_Texture_SecondaryGloss;
761         int loc_Texture_SecondaryGlow;
762         int loc_Texture_Pants;
763         int loc_Texture_Shirt;
764         int loc_Texture_FogHeightTexture;
765         int loc_Texture_FogMask;
766         int loc_Texture_Lightmap;
767         int loc_Texture_Deluxemap;
768         int loc_Texture_Attenuation;
769         int loc_Texture_Cube;
770         int loc_Texture_Refraction;
771         int loc_Texture_Reflection;
772         int loc_Texture_ShadowMap2D;
773         int loc_Texture_CubeProjection;
774         int loc_Texture_ScreenNormalMap;
775         int loc_Texture_ScreenDiffuse;
776         int loc_Texture_ScreenSpecular;
777         int loc_Texture_ReflectMask;
778         int loc_Texture_ReflectCube;
779         int loc_Texture_BounceGrid;
780         int loc_Alpha;
781         int loc_BloomBlur_Parameters;
782         int loc_ClientTime;
783         int loc_Color_Ambient;
784         int loc_Color_Diffuse;
785         int loc_Color_Specular;
786         int loc_Color_Glow;
787         int loc_Color_Pants;
788         int loc_Color_Shirt;
789         int loc_DeferredColor_Ambient;
790         int loc_DeferredColor_Diffuse;
791         int loc_DeferredColor_Specular;
792         int loc_DeferredMod_Diffuse;
793         int loc_DeferredMod_Specular;
794         int loc_DistortScaleRefractReflect;
795         int loc_EyePosition;
796         int loc_FogColor;
797         int loc_FogHeightFade;
798         int loc_FogPlane;
799         int loc_FogPlaneViewDist;
800         int loc_FogRangeRecip;
801         int loc_LightColor;
802         int loc_LightDir;
803         int loc_LightPosition;
804         int loc_OffsetMapping_ScaleSteps;
805         int loc_OffsetMapping_LodDistance;
806         int loc_OffsetMapping_Bias;
807         int loc_PixelSize;
808         int loc_ReflectColor;
809         int loc_ReflectFactor;
810         int loc_ReflectOffset;
811         int loc_RefractColor;
812         int loc_Saturation;
813         int loc_ScreenCenterRefractReflect;
814         int loc_ScreenScaleRefractReflect;
815         int loc_ScreenToDepth;
816         int loc_ShadowMap_Parameters;
817         int loc_ShadowMap_TextureScale;
818         int loc_SpecularPower;
819         int loc_UserVec1;
820         int loc_UserVec2;
821         int loc_UserVec3;
822         int loc_UserVec4;
823         int loc_ViewTintColor;
824         int loc_ViewToLight;
825         int loc_ModelToLight;
826         int loc_TexMatrix;
827         int loc_BackgroundTexMatrix;
828         int loc_ModelViewProjectionMatrix;
829         int loc_ModelViewMatrix;
830         int loc_PixelToScreenTexCoord;
831         int loc_ModelToReflectCube;
832         int loc_ShadowMapMatrix;
833         int loc_BloomColorSubtract;
834         int loc_NormalmapScrollBlend;
835         int loc_BounceGridMatrix;
836         int loc_BounceGridIntensity;
837 }
838 r_glsl_permutation_t;
839
840 #define SHADERPERMUTATION_HASHSIZE 256
841
842
843 // non-degradable "lightweight" shader parameters to keep the permutations simpler
844 // these can NOT degrade! only use for simple stuff
845 enum
846 {
847         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
848         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
849         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
851         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
853         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
854         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
855         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
856         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
857         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
858         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
859         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
860 };
861 #define SHADERSTATICPARMS_COUNT 13
862
863 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
864 static int shaderstaticparms_count = 0;
865
866 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
867 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
868
869 extern qboolean r_shadow_shadowmapsampler;
870 extern int r_shadow_shadowmappcf;
871 qboolean R_CompileShader_CheckStaticParms(void)
872 {
873         static int r_compileshader_staticparms_save[1];
874         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
876
877         // detect all
878         if (r_glsl_saturation_redcompensate.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880         if (r_glsl_vertextextureblend_usebothalphas.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882         if (r_shadow_glossexact.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884         if (r_glsl_postprocess.integer)
885         {
886                 if (r_glsl_postprocess_uservec1_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888                 if (r_glsl_postprocess_uservec2_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890                 if (r_glsl_postprocess_uservec3_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892                 if (r_glsl_postprocess_uservec4_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894         }
895         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
897
898         if (r_shadow_shadowmapsampler)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
900         if (r_shadow_shadowmappcf > 1)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
902         else if (r_shadow_shadowmappcf)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
904         else if (r_celshading.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
906         else if (r_celoutlines.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
908
909         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
910 }
911
912 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
913         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
914                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
915         else \
916                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
917 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
918 {
919         shaderstaticparms_count = 0;
920
921         // emit all
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
935 }
936
937 /// information about each possible shader permutation
938 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
939 /// currently selected permutation
940 r_glsl_permutation_t *r_glsl_permutation;
941 /// storage for permutations linked in the hash table
942 memexpandablearray_t r_glsl_permutationarray;
943
944 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
945 {
946         //unsigned int hashdepth = 0;
947         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
948         r_glsl_permutation_t *p;
949         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
950         {
951                 if (p->mode == mode && p->permutation == permutation)
952                 {
953                         //if (hashdepth > 10)
954                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955                         return p;
956                 }
957                 //hashdepth++;
958         }
959         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
960         p->mode = mode;
961         p->permutation = permutation;
962         p->hashnext = r_glsl_permutationhash[mode][hashindex];
963         r_glsl_permutationhash[mode][hashindex] = p;
964         //if (hashdepth > 10)
965         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
966         return p;
967 }
968
969 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
970 {
971         char *shaderstring;
972         if (!filename || !filename[0])
973                 return NULL;
974         if (!strcmp(filename, "glsl/default.glsl"))
975         {
976                 if (!glslshaderstring)
977                 {
978                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979                         if (glslshaderstring)
980                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
981                         else
982                                 glslshaderstring = (char *)builtinshaderstring;
983                 }
984                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
985                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
986                 return shaderstring;
987         }
988         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
989         if (shaderstring)
990         {
991                 if (printfromdisknotice)
992                         Con_DPrintf("from disk %s... ", filename);
993                 return shaderstring;
994         }
995         return shaderstring;
996 }
997
998 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
999 {
1000         int i;
1001         int sampler;
1002         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1003         char *vertexstring, *geometrystring, *fragmentstring;
1004         char permutationname[256];
1005         int vertstrings_count = 0;
1006         int geomstrings_count = 0;
1007         int fragstrings_count = 0;
1008         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1009         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1010         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1011
1012         if (p->compiled)
1013                 return;
1014         p->compiled = true;
1015         p->program = 0;
1016
1017         permutationname[0] = 0;
1018         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1019         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1020         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1021
1022         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1023
1024         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1025         if(vid.support.gl20shaders130)
1026         {
1027                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1028                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1029                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1030                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1031                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1032                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1033         }
1034
1035         // the first pretext is which type of shader to compile as
1036         // (later these will all be bound together as a program object)
1037         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1038         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1039         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1040
1041         // the second pretext is the mode (for example a light source)
1042         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1043         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1044         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1045         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1046
1047         // now add all the permutation pretexts
1048         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1049         {
1050                 if (permutation & (1<<i))
1051                 {
1052                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1056                 }
1057                 else
1058                 {
1059                         // keep line numbers correct
1060                         vertstrings_list[vertstrings_count++] = "\n";
1061                         geomstrings_list[geomstrings_count++] = "\n";
1062                         fragstrings_list[fragstrings_count++] = "\n";
1063                 }
1064         }
1065
1066         // add static parms
1067         R_CompileShader_AddStaticParms(mode, permutation);
1068         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1069         vertstrings_count += shaderstaticparms_count;
1070         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         geomstrings_count += shaderstaticparms_count;
1072         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073         fragstrings_count += shaderstaticparms_count;
1074
1075         // now append the shader text itself
1076         vertstrings_list[vertstrings_count++] = vertexstring;
1077         geomstrings_list[geomstrings_count++] = geometrystring;
1078         fragstrings_list[fragstrings_count++] = fragmentstring;
1079
1080         // if any sources were NULL, clear the respective list
1081         if (!vertexstring)
1082                 vertstrings_count = 0;
1083         if (!geometrystring)
1084                 geomstrings_count = 0;
1085         if (!fragmentstring)
1086                 fragstrings_count = 0;
1087
1088         // compile the shader program
1089         if (vertstrings_count + geomstrings_count + fragstrings_count)
1090                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1091         if (p->program)
1092         {
1093                 CHECKGLERROR
1094                 qglUseProgram(p->program);CHECKGLERROR
1095                 // look up all the uniform variable names we care about, so we don't
1096                 // have to look them up every time we set them
1097
1098                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1099                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1100                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1101                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1102                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1103                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1104                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1105                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1106                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1107                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1108                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1109                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1110                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1111                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1112                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1113                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1114                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1115                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1116                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1117                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1118                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1119                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1120                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1121                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1128                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1130                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1131                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1132                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1133                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1134                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1135                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1136                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1143                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1144                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1145                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1146                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1148                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1149                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1150                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1151                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1154                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1155                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1156                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1157                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1158                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1159                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1160                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1161                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1162                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1163                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1164                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1165                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1166                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1167                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1168                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1169                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1170                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1171                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1172                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1173                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1174                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1175                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1176                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1177                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1178                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1179                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1180                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1181                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1182                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1183                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1184                 // initialize the samplers to refer to the texture units we use
1185                 p->tex_Texture_First = -1;
1186                 p->tex_Texture_Second = -1;
1187                 p->tex_Texture_GammaRamps = -1;
1188                 p->tex_Texture_Normal = -1;
1189                 p->tex_Texture_Color = -1;
1190                 p->tex_Texture_Gloss = -1;
1191                 p->tex_Texture_Glow = -1;
1192                 p->tex_Texture_SecondaryNormal = -1;
1193                 p->tex_Texture_SecondaryColor = -1;
1194                 p->tex_Texture_SecondaryGloss = -1;
1195                 p->tex_Texture_SecondaryGlow = -1;
1196                 p->tex_Texture_Pants = -1;
1197                 p->tex_Texture_Shirt = -1;
1198                 p->tex_Texture_FogHeightTexture = -1;
1199                 p->tex_Texture_FogMask = -1;
1200                 p->tex_Texture_Lightmap = -1;
1201                 p->tex_Texture_Deluxemap = -1;
1202                 p->tex_Texture_Attenuation = -1;
1203                 p->tex_Texture_Cube = -1;
1204                 p->tex_Texture_Refraction = -1;
1205                 p->tex_Texture_Reflection = -1;
1206                 p->tex_Texture_ShadowMap2D = -1;
1207                 p->tex_Texture_CubeProjection = -1;
1208                 p->tex_Texture_ScreenNormalMap = -1;
1209                 p->tex_Texture_ScreenDiffuse = -1;
1210                 p->tex_Texture_ScreenSpecular = -1;
1211                 p->tex_Texture_ReflectMask = -1;
1212                 p->tex_Texture_ReflectCube = -1;
1213                 p->tex_Texture_BounceGrid = -1;
1214                 sampler = 0;
1215                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1216                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1217                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1218                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1219                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1220                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1221                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1222                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1226                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1227                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1228                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1229                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1230                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1231                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1232                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1233                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1234                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1235                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1236                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1237                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1238                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1241                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1243                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1244                 CHECKGLERROR
1245                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1246         }
1247         else
1248                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1249
1250         // free the strings
1251         if (vertexstring)
1252                 Mem_Free(vertexstring);
1253         if (geometrystring)
1254                 Mem_Free(geometrystring);
1255         if (fragmentstring)
1256                 Mem_Free(fragmentstring);
1257 }
1258
1259 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1260 {
1261         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1262         if (r_glsl_permutation != perm)
1263         {
1264                 r_glsl_permutation = perm;
1265                 if (!r_glsl_permutation->program)
1266                 {
1267                         if (!r_glsl_permutation->compiled)
1268                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                         if (!r_glsl_permutation->program)
1270                         {
1271                                 // remove features until we find a valid permutation
1272                                 int i;
1273                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1274                                 {
1275                                         // reduce i more quickly whenever it would not remove any bits
1276                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1277                                         if (!(permutation & j))
1278                                                 continue;
1279                                         permutation -= j;
1280                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1281                                         if (!r_glsl_permutation->compiled)
1282                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1283                                         if (r_glsl_permutation->program)
1284                                                 break;
1285                                 }
1286                                 if (i >= SHADERPERMUTATION_COUNT)
1287                                 {
1288                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1289                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1290                                         qglUseProgram(0);CHECKGLERROR
1291                                         return; // no bit left to clear, entire mode is broken
1292                                 }
1293                         }
1294                 }
1295                 CHECKGLERROR
1296                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1297         }
1298         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1299         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1300         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1301 }
1302
1303 #ifdef SUPPORTD3D
1304
1305 #ifdef SUPPORTD3D
1306 #include <d3d9.h>
1307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1308 extern D3DCAPS9 vid_d3d9caps;
1309 #endif
1310
1311 struct r_hlsl_permutation_s;
1312 typedef struct r_hlsl_permutation_s
1313 {
1314         /// hash lookup data
1315         struct r_hlsl_permutation_s *hashnext;
1316         unsigned int mode;
1317         unsigned int permutation;
1318
1319         /// indicates if we have tried compiling this permutation already
1320         qboolean compiled;
1321         /// NULL if compilation failed
1322         IDirect3DVertexShader9 *vertexshader;
1323         IDirect3DPixelShader9 *pixelshader;
1324 }
1325 r_hlsl_permutation_t;
1326
1327 typedef enum D3DVSREGISTER_e
1328 {
1329         D3DVSREGISTER_TexMatrix = 0, // float4x4
1330         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1331         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1332         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1333         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1334         D3DVSREGISTER_ModelToLight = 20, // float4x4
1335         D3DVSREGISTER_EyePosition = 24,
1336         D3DVSREGISTER_FogPlane = 25,
1337         D3DVSREGISTER_LightDir = 26,
1338         D3DVSREGISTER_LightPosition = 27,
1339 }
1340 D3DVSREGISTER_t;
1341
1342 typedef enum D3DPSREGISTER_e
1343 {
1344         D3DPSREGISTER_Alpha = 0,
1345         D3DPSREGISTER_BloomBlur_Parameters = 1,
1346         D3DPSREGISTER_ClientTime = 2,
1347         D3DPSREGISTER_Color_Ambient = 3,
1348         D3DPSREGISTER_Color_Diffuse = 4,
1349         D3DPSREGISTER_Color_Specular = 5,
1350         D3DPSREGISTER_Color_Glow = 6,
1351         D3DPSREGISTER_Color_Pants = 7,
1352         D3DPSREGISTER_Color_Shirt = 8,
1353         D3DPSREGISTER_DeferredColor_Ambient = 9,
1354         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1355         D3DPSREGISTER_DeferredColor_Specular = 11,
1356         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1357         D3DPSREGISTER_DeferredMod_Specular = 13,
1358         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1359         D3DPSREGISTER_EyePosition = 15, // unused
1360         D3DPSREGISTER_FogColor = 16,
1361         D3DPSREGISTER_FogHeightFade = 17,
1362         D3DPSREGISTER_FogPlane = 18,
1363         D3DPSREGISTER_FogPlaneViewDist = 19,
1364         D3DPSREGISTER_FogRangeRecip = 20,
1365         D3DPSREGISTER_LightColor = 21,
1366         D3DPSREGISTER_LightDir = 22, // unused
1367         D3DPSREGISTER_LightPosition = 23,
1368         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1369         D3DPSREGISTER_PixelSize = 25,
1370         D3DPSREGISTER_ReflectColor = 26,
1371         D3DPSREGISTER_ReflectFactor = 27,
1372         D3DPSREGISTER_ReflectOffset = 28,
1373         D3DPSREGISTER_RefractColor = 29,
1374         D3DPSREGISTER_Saturation = 30,
1375         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1376         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1377         D3DPSREGISTER_ScreenToDepth = 33,
1378         D3DPSREGISTER_ShadowMap_Parameters = 34,
1379         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1380         D3DPSREGISTER_SpecularPower = 36,
1381         D3DPSREGISTER_UserVec1 = 37,
1382         D3DPSREGISTER_UserVec2 = 38,
1383         D3DPSREGISTER_UserVec3 = 39,
1384         D3DPSREGISTER_UserVec4 = 40,
1385         D3DPSREGISTER_ViewTintColor = 41,
1386         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1387         D3DPSREGISTER_BloomColorSubtract = 43,
1388         D3DPSREGISTER_ViewToLight = 44, // float4x4
1389         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1390         D3DPSREGISTER_NormalmapScrollBlend = 52,
1391         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1392         D3DPSREGISTER_OffsetMapping_Bias = 54,
1393         // next at 54
1394 }
1395 D3DPSREGISTER_t;
1396
1397 /// information about each possible shader permutation
1398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1399 /// currently selected permutation
1400 r_hlsl_permutation_t *r_hlsl_permutation;
1401 /// storage for permutations linked in the hash table
1402 memexpandablearray_t r_hlsl_permutationarray;
1403
1404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1405 {
1406         //unsigned int hashdepth = 0;
1407         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1408         r_hlsl_permutation_t *p;
1409         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1410         {
1411                 if (p->mode == mode && p->permutation == permutation)
1412                 {
1413                         //if (hashdepth > 10)
1414                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415                         return p;
1416                 }
1417                 //hashdepth++;
1418         }
1419         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1420         p->mode = mode;
1421         p->permutation = permutation;
1422         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1423         r_hlsl_permutationhash[mode][hashindex] = p;
1424         //if (hashdepth > 10)
1425         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1426         return p;
1427 }
1428
1429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1430 {
1431         char *shaderstring;
1432         if (!filename || !filename[0])
1433                 return NULL;
1434         if (!strcmp(filename, "hlsl/default.hlsl"))
1435         {
1436                 if (!hlslshaderstring)
1437                 {
1438                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439                         if (hlslshaderstring)
1440                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1441                         else
1442                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1443                 }
1444                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1445                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1446                 return shaderstring;
1447         }
1448         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449         if (shaderstring)
1450         {
1451                 if (printfromdisknotice)
1452                         Con_DPrintf("from disk %s... ", filename);
1453                 return shaderstring;
1454         }
1455         return shaderstring;
1456 }
1457
1458 #include <d3dx9.h>
1459 //#include <d3dx9shader.h>
1460 //#include <d3dx9mesh.h>
1461
1462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1463 {
1464         DWORD *vsbin = NULL;
1465         DWORD *psbin = NULL;
1466         fs_offset_t vsbinsize;
1467         fs_offset_t psbinsize;
1468 //      IDirect3DVertexShader9 *vs = NULL;
1469 //      IDirect3DPixelShader9 *ps = NULL;
1470         ID3DXBuffer *vslog = NULL;
1471         ID3DXBuffer *vsbuffer = NULL;
1472         ID3DXConstantTable *vsconstanttable = NULL;
1473         ID3DXBuffer *pslog = NULL;
1474         ID3DXBuffer *psbuffer = NULL;
1475         ID3DXConstantTable *psconstanttable = NULL;
1476         int vsresult = 0;
1477         int psresult = 0;
1478         char temp[MAX_INPUTLINE];
1479         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1480         char vabuf[1024];
1481         qboolean debugshader = gl_paranoid.integer != 0;
1482         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1483         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484         if (!debugshader)
1485         {
1486                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1487                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1488         }
1489         if ((!vsbin && vertstring) || (!psbin && fragstring))
1490         {
1491                 const char* dllnames_d3dx9 [] =
1492                 {
1493                         "d3dx9_43.dll",
1494                         "d3dx9_42.dll",
1495                         "d3dx9_41.dll",
1496                         "d3dx9_40.dll",
1497                         "d3dx9_39.dll",
1498                         "d3dx9_38.dll",
1499                         "d3dx9_37.dll",
1500                         "d3dx9_36.dll",
1501                         "d3dx9_35.dll",
1502                         "d3dx9_34.dll",
1503                         "d3dx9_33.dll",
1504                         "d3dx9_32.dll",
1505                         "d3dx9_31.dll",
1506                         "d3dx9_30.dll",
1507                         "d3dx9_29.dll",
1508                         "d3dx9_28.dll",
1509                         "d3dx9_27.dll",
1510                         "d3dx9_26.dll",
1511                         "d3dx9_25.dll",
1512                         "d3dx9_24.dll",
1513                         NULL
1514                 };
1515                 dllhandle_t d3dx9_dll = NULL;
1516                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1517                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1518                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1519                 dllfunction_t d3dx9_dllfuncs[] =
1520                 {
1521                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1522                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1523                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1524                         {NULL, NULL}
1525                 };
1526                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1527                 {
1528                         DWORD shaderflags = 0;
1529                         if (debugshader)
1530                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1531                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1532                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1533                         if (vertstring && vertstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1538 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1539                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1540                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1541                                 }
1542                                 else
1543                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544                                 if (vsbuffer)
1545                                 {
1546                                         vsbinsize = vsbuffer->GetBufferSize();
1547                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1548                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1549                                         vsbuffer->Release();
1550                                 }
1551                                 if (vslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         vslog->Release();
1556                                 }
1557                         }
1558                         if (fragstring && fragstring[0])
1559                         {
1560                                 if (debugshader)
1561                                 {
1562 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1563 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1564                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1565                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1566                                 }
1567                                 else
1568                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1569                                 if (psbuffer)
1570                                 {
1571                                         psbinsize = psbuffer->GetBufferSize();
1572                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1573                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1574                                         psbuffer->Release();
1575                                 }
1576                                 if (pslog)
1577                                 {
1578                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1579                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1580                                         pslog->Release();
1581                                 }
1582                         }
1583                         Sys_UnloadLibrary(&d3dx9_dll);
1584                 }
1585                 else
1586                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1587         }
1588         if (vsbin && psbin)
1589         {
1590                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1591                 if (FAILED(vsresult))
1592                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1593                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1594                 if (FAILED(psresult))
1595                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1596         }
1597         // free the shader data
1598         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1599         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1600 }
1601
1602 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1603 {
1604         int i;
1605         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1606         int vertstring_length = 0;
1607         int geomstring_length = 0;
1608         int fragstring_length = 0;
1609         char *t;
1610         char *vertexstring, *geometrystring, *fragmentstring;
1611         char *vertstring, *geomstring, *fragstring;
1612         char permutationname[256];
1613         char cachename[256];
1614         int vertstrings_count = 0;
1615         int geomstrings_count = 0;
1616         int fragstrings_count = 0;
1617         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1618         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1619         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1620
1621         if (p->compiled)
1622                 return;
1623         p->compiled = true;
1624         p->vertexshader = NULL;
1625         p->pixelshader = NULL;
1626
1627         permutationname[0] = 0;
1628         cachename[0] = 0;
1629         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1630         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1631         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1632
1633         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1634         strlcat(cachename, "hlsl/", sizeof(cachename));
1635
1636         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1637         vertstrings_count = 0;
1638         geomstrings_count = 0;
1639         fragstrings_count = 0;
1640         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1641         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1642         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1643
1644         // the first pretext is which type of shader to compile as
1645         // (later these will all be bound together as a program object)
1646         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1647         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1648         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1649
1650         // the second pretext is the mode (for example a light source)
1651         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1652         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1653         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1654         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1655         strlcat(cachename, modeinfo->name, sizeof(cachename));
1656
1657         // now add all the permutation pretexts
1658         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1659         {
1660                 if (permutation & (1<<i))
1661                 {
1662                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1663                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1666                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1667                 }
1668                 else
1669                 {
1670                         // keep line numbers correct
1671                         vertstrings_list[vertstrings_count++] = "\n";
1672                         geomstrings_list[geomstrings_count++] = "\n";
1673                         fragstrings_list[fragstrings_count++] = "\n";
1674                 }
1675         }
1676
1677         // add static parms
1678         R_CompileShader_AddStaticParms(mode, permutation);
1679         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1680         vertstrings_count += shaderstaticparms_count;
1681         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682         geomstrings_count += shaderstaticparms_count;
1683         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684         fragstrings_count += shaderstaticparms_count;
1685
1686         // replace spaces in the cachename with _ characters
1687         for (i = 0;cachename[i];i++)
1688                 if (cachename[i] == ' ')
1689                         cachename[i] = '_';
1690
1691         // now append the shader text itself
1692         vertstrings_list[vertstrings_count++] = vertexstring;
1693         geomstrings_list[geomstrings_count++] = geometrystring;
1694         fragstrings_list[fragstrings_count++] = fragmentstring;
1695
1696         // if any sources were NULL, clear the respective list
1697         if (!vertexstring)
1698                 vertstrings_count = 0;
1699         if (!geometrystring)
1700                 geomstrings_count = 0;
1701         if (!fragmentstring)
1702                 fragstrings_count = 0;
1703
1704         vertstring_length = 0;
1705         for (i = 0;i < vertstrings_count;i++)
1706                 vertstring_length += strlen(vertstrings_list[i]);
1707         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1708         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1709                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1710
1711         geomstring_length = 0;
1712         for (i = 0;i < geomstrings_count;i++)
1713                 geomstring_length += strlen(geomstrings_list[i]);
1714         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1715         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1716                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1717
1718         fragstring_length = 0;
1719         for (i = 0;i < fragstrings_count;i++)
1720                 fragstring_length += strlen(fragstrings_list[i]);
1721         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1722         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1723                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1724
1725         // try to load the cached shader, or generate one
1726         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1727
1728         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1729                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1730         else
1731                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1732
1733         // free the strings
1734         if (vertstring)
1735                 Mem_Free(vertstring);
1736         if (geomstring)
1737                 Mem_Free(geomstring);
1738         if (fragstring)
1739                 Mem_Free(fragstring);
1740         if (vertexstring)
1741                 Mem_Free(vertexstring);
1742         if (geometrystring)
1743                 Mem_Free(geometrystring);
1744         if (fragmentstring)
1745                 Mem_Free(fragmentstring);
1746 }
1747
1748 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1749 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1750 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);}
1751 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);}
1752 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);}
1753 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);}
1754
1755 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1756 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1757 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);}
1758 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);}
1759 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);}
1760 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);}
1761
1762 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1763 {
1764         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1765         if (r_hlsl_permutation != perm)
1766         {
1767                 r_hlsl_permutation = perm;
1768                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1769                 {
1770                         if (!r_hlsl_permutation->compiled)
1771                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1772                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773                         {
1774                                 // remove features until we find a valid permutation
1775                                 int i;
1776                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777                                 {
1778                                         // reduce i more quickly whenever it would not remove any bits
1779                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1780                                         if (!(permutation & j))
1781                                                 continue;
1782                                         permutation -= j;
1783                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1784                                         if (!r_hlsl_permutation->compiled)
1785                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1786                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1787                                                 break;
1788                                 }
1789                                 if (i >= SHADERPERMUTATION_COUNT)
1790                                 {
1791                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1792                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1793                                         return; // no bit left to clear, entire mode is broken
1794                                 }
1795                         }
1796                 }
1797                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1798                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1799         }
1800         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1802         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1803 }
1804 #endif
1805
1806 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1807 {
1808         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1809         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1810         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1811         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1812 }
1813
1814 void R_GLSL_Restart_f(void)
1815 {
1816         unsigned int i, limit;
1817         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1818                 Mem_Free(glslshaderstring);
1819         glslshaderstring = NULL;
1820         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1821                 Mem_Free(hlslshaderstring);
1822         hlslshaderstring = NULL;
1823         switch(vid.renderpath)
1824         {
1825         case RENDERPATH_D3D9:
1826 #ifdef SUPPORTD3D
1827                 {
1828                         r_hlsl_permutation_t *p;
1829                         r_hlsl_permutation = NULL;
1830                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1831                         for (i = 0;i < limit;i++)
1832                         {
1833                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1834                                 {
1835                                         if (p->vertexshader)
1836                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1837                                         if (p->pixelshader)
1838                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1839                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1840                                 }
1841                         }
1842                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1843                 }
1844 #endif
1845                 break;
1846         case RENDERPATH_D3D10:
1847                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1848                 break;
1849         case RENDERPATH_D3D11:
1850                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1851                 break;
1852         case RENDERPATH_GL20:
1853         case RENDERPATH_GLES2:
1854                 {
1855                         r_glsl_permutation_t *p;
1856                         r_glsl_permutation = NULL;
1857                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1858                         for (i = 0;i < limit;i++)
1859                         {
1860                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1861                                 {
1862                                         GL_Backend_FreeProgram(p->program);
1863                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1864                                 }
1865                         }
1866                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1867                 }
1868                 break;
1869         case RENDERPATH_GL11:
1870         case RENDERPATH_GL13:
1871         case RENDERPATH_GLES1:
1872                 break;
1873         case RENDERPATH_SOFT:
1874                 break;
1875         }
1876 }
1877
1878 static void R_GLSL_DumpShader_f(void)
1879 {
1880         int i;
1881         qfile_t *file;
1882
1883         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1884         if (file)
1885         {
1886                 FS_Print(file, "/* The engine may define the following macros:\n");
1887                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888                 for (i = 0;i < SHADERMODE_COUNT;i++)
1889                         FS_Print(file, glslshadermodeinfo[i].pretext);
1890                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891                         FS_Print(file, shaderpermutationinfo[i].pretext);
1892                 FS_Print(file, "*/\n");
1893                 FS_Print(file, builtinshaderstring);
1894                 FS_Close(file);
1895                 Con_Printf("glsl/default.glsl written\n");
1896         }
1897         else
1898                 Con_Printf("failed to write to glsl/default.glsl\n");
1899
1900         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1901         if (file)
1902         {
1903                 FS_Print(file, "/* The engine may define the following macros:\n");
1904                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1905                 for (i = 0;i < SHADERMODE_COUNT;i++)
1906                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1907                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1908                         FS_Print(file, shaderpermutationinfo[i].pretext);
1909                 FS_Print(file, "*/\n");
1910                 FS_Print(file, builtinhlslshaderstring);
1911                 FS_Close(file);
1912                 Con_Printf("hlsl/default.hlsl written\n");
1913         }
1914         else
1915                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1916 }
1917
1918 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1919 {
1920         unsigned int permutation = 0;
1921         if (r_trippy.integer && !notrippy)
1922                 permutation |= SHADERPERMUTATION_TRIPPY;
1923         permutation |= SHADERPERMUTATION_VIEWTINT;
1924         if (first)
1925                 permutation |= SHADERPERMUTATION_DIFFUSE;
1926         if (second)
1927                 permutation |= SHADERPERMUTATION_SPECULAR;
1928         if (texturemode == GL_MODULATE)
1929                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1930         else if (texturemode == GL_ADD)
1931                 permutation |= SHADERPERMUTATION_GLOW;
1932         else if (texturemode == GL_DECAL)
1933                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1934         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1935                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1936         if (suppresstexalpha)
1937                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1938         if (!second)
1939                 texturemode = GL_MODULATE;
1940         if (vid.allowalphatocoverage)
1941                 GL_AlphaToCoverage(false);
1942         switch (vid.renderpath)
1943         {
1944         case RENDERPATH_D3D9:
1945 #ifdef SUPPORTD3D
1946                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1947                 R_Mesh_TexBind(GL20TU_FIRST , first );
1948                 R_Mesh_TexBind(GL20TU_SECOND, second);
1949                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1950                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1951 #endif
1952                 break;
1953         case RENDERPATH_D3D10:
1954                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955                 break;
1956         case RENDERPATH_D3D11:
1957                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958                 break;
1959         case RENDERPATH_GL20:
1960         case RENDERPATH_GLES2:
1961                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1962                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1964                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1965                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1966                 break;
1967         case RENDERPATH_GL13:
1968         case RENDERPATH_GLES1:
1969                 R_Mesh_TexBind(0, first );
1970                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1971                 R_Mesh_TexBind(1, second);
1972                 if (second)
1973                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1974                 break;
1975         case RENDERPATH_GL11:
1976                 R_Mesh_TexBind(0, first );
1977                 break;
1978         case RENDERPATH_SOFT:
1979                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1980                 R_Mesh_TexBind(GL20TU_FIRST , first );
1981                 R_Mesh_TexBind(GL20TU_SECOND, second);
1982                 break;
1983         }
1984 }
1985
1986 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1987 {
1988         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1989 }
1990
1991 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1992 {
1993         unsigned int permutation = 0;
1994         if (r_trippy.integer && !notrippy)
1995                 permutation |= SHADERPERMUTATION_TRIPPY;
1996         if (depthrgb)
1997                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1998         if (vid.allowalphatocoverage)
1999                 GL_AlphaToCoverage(false);
2000         switch (vid.renderpath)
2001         {
2002         case RENDERPATH_D3D9:
2003 #ifdef SUPPORTD3D
2004                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2005 #endif
2006                 break;
2007         case RENDERPATH_D3D10:
2008                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2009                 break;
2010         case RENDERPATH_D3D11:
2011                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2012                 break;
2013         case RENDERPATH_GL20:
2014         case RENDERPATH_GLES2:
2015                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2016                 break;
2017         case RENDERPATH_GL13:
2018         case RENDERPATH_GLES1:
2019                 R_Mesh_TexBind(0, 0);
2020                 R_Mesh_TexBind(1, 0);
2021                 break;
2022         case RENDERPATH_GL11:
2023                 R_Mesh_TexBind(0, 0);
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2027                 break;
2028         }
2029 }
2030
2031 void R_SetupShader_ShowDepth(qboolean notrippy)
2032 {
2033         int permutation = 0;
2034         if (r_trippy.integer && !notrippy)
2035                 permutation |= SHADERPERMUTATION_TRIPPY;
2036         if (vid.allowalphatocoverage)
2037                 GL_AlphaToCoverage(false);
2038         switch (vid.renderpath)
2039         {
2040         case RENDERPATH_D3D9:
2041 #ifdef SUPPORTHLSL
2042                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2043 #endif
2044                 break;
2045         case RENDERPATH_D3D10:
2046                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2047                 break;
2048         case RENDERPATH_D3D11:
2049                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2050                 break;
2051         case RENDERPATH_GL20:
2052         case RENDERPATH_GLES2:
2053                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2054                 break;
2055         case RENDERPATH_GL13:
2056         case RENDERPATH_GLES1:
2057                 break;
2058         case RENDERPATH_GL11:
2059                 break;
2060         case RENDERPATH_SOFT:
2061                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2062                 break;
2063         }
2064 }
2065
2066 extern qboolean r_shadow_usingdeferredprepass;
2067 extern rtexture_t *r_shadow_attenuationgradienttexture;
2068 extern rtexture_t *r_shadow_attenuation2dtexture;
2069 extern rtexture_t *r_shadow_attenuation3dtexture;
2070 extern qboolean r_shadow_usingshadowmap2d;
2071 extern qboolean r_shadow_usingshadowmaportho;
2072 extern float r_shadow_shadowmap_texturescale[2];
2073 extern float r_shadow_shadowmap_parameters[4];
2074 extern qboolean r_shadow_shadowmapvsdct;
2075 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2076 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2077 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2078 extern matrix4x4_t r_shadow_shadowmapmatrix;
2079 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2080 extern int r_shadow_prepass_width;
2081 extern int r_shadow_prepass_height;
2082 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2083 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2084 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2085 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2086
2087 #define BLENDFUNC_ALLOWS_COLORMOD      1
2088 #define BLENDFUNC_ALLOWS_FOG           2
2089 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2090 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2091 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2092 static int R_BlendFuncFlags(int src, int dst)
2093 {
2094         int r = 0;
2095
2096         // a blendfunc allows colormod if:
2097         // a) it can never keep the destination pixel invariant, or
2098         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2099         // this is to prevent unintended side effects from colormod
2100
2101         // a blendfunc allows fog if:
2102         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2103         // this is to prevent unintended side effects from fog
2104
2105         // these checks are the output of fogeval.pl
2106
2107         r |= BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2117         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2123         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2124         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2125         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2126         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2127         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2129
2130         return r;
2131 }
2132
2133 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)
2134 {
2135         // select a permutation of the lighting shader appropriate to this
2136         // combination of texture, entity, light source, and fogging, only use the
2137         // minimum features necessary to avoid wasting rendering time in the
2138         // fragment shader on features that are not being used
2139         unsigned int permutation = 0;
2140         unsigned int mode = 0;
2141         int blendfuncflags;
2142         static float dummy_colormod[3] = {1, 1, 1};
2143         float *colormod = rsurface.colormod;
2144         float m16f[16];
2145         matrix4x4_t tempmatrix;
2146         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2147         if (r_trippy.integer && !notrippy)
2148                 permutation |= SHADERPERMUTATION_TRIPPY;
2149         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2150                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2151         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2152                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2153         if (rsurfacepass == RSURFPASS_BACKGROUND)
2154         {
2155                 // distorted background
2156                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2157                 {
2158                         mode = SHADERMODE_WATER;
2159                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2160                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2161                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2162                         {
2163                                 // this is the right thing to do for wateralpha
2164                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2165                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2166                         }
2167                         else
2168                         {
2169                                 // this is the right thing to do for entity alpha
2170                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172                         }
2173                 }
2174                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2175                 {
2176                         mode = SHADERMODE_REFRACTION;
2177                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2178                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2179                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2180                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2181                 }
2182                 else
2183                 {
2184                         mode = SHADERMODE_GENERIC;
2185                         permutation |= SHADERPERMUTATION_DIFFUSE;
2186                         GL_BlendFunc(GL_ONE, GL_ZERO);
2187                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2188                 }
2189                 if (vid.allowalphatocoverage)
2190                         GL_AlphaToCoverage(false);
2191         }
2192         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2193         {
2194                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2195                 {
2196                         switch(rsurface.texture->offsetmapping)
2197                         {
2198                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2199                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_OFF: break;
2202                         }
2203                 }
2204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2205                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2206                 // normalmap (deferred prepass), may use alpha test on diffuse
2207                 mode = SHADERMODE_DEFERREDGEOMETRY;
2208                 GL_BlendFunc(GL_ONE, GL_ZERO);
2209                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2210                 if (vid.allowalphatocoverage)
2211                         GL_AlphaToCoverage(false);
2212         }
2213         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2214         {
2215                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2216                 {
2217                         switch(rsurface.texture->offsetmapping)
2218                         {
2219                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2220                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222                         case OFFSETMAPPING_OFF: break;
2223                         }
2224                 }
2225                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2226                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2227                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229                 // light source
2230                 mode = SHADERMODE_LIGHTSOURCE;
2231                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2232                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2233                 if (diffusescale > 0)
2234                         permutation |= SHADERPERMUTATION_DIFFUSE;
2235                 if (specularscale > 0)
2236                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2237                 if (r_refdef.fogenabled)
2238                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2239                 if (rsurface.texture->colormapping)
2240                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2241                 if (r_shadow_usingshadowmap2d)
2242                 {
2243                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2244                         if(r_shadow_shadowmapvsdct)
2245                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2246
2247                         if (r_shadow_shadowmap2ddepthbuffer)
2248                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2249                 }
2250                 if (rsurface.texture->reflectmasktexture)
2251                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2252                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2253                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2254                 if (vid.allowalphatocoverage)
2255                         GL_AlphaToCoverage(false);
2256         }
2257         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2258         {
2259                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2260                 {
2261                         switch(rsurface.texture->offsetmapping)
2262                         {
2263                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2264                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2265                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266                         case OFFSETMAPPING_OFF: break;
2267                         }
2268                 }
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2270                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2272                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2273                 // unshaded geometry (fullbright or ambient model lighting)
2274                 mode = SHADERMODE_FLATCOLOR;
2275                 ambientscale = diffusescale = specularscale = 0;
2276                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2277                         permutation |= SHADERPERMUTATION_GLOW;
2278                 if (r_refdef.fogenabled)
2279                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2280                 if (rsurface.texture->colormapping)
2281                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2282                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2283                 {
2284                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2285                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2286
2287                         if (r_shadow_shadowmap2ddepthbuffer)
2288                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2291                         permutation |= SHADERPERMUTATION_REFLECTION;
2292                 if (rsurface.texture->reflectmasktexture)
2293                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2294                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2295                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2296                 // when using alphatocoverage, we don't need alphakill
2297                 if (vid.allowalphatocoverage)
2298                 {
2299                         if (r_transparent_alphatocoverage.integer)
2300                         {
2301                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2302                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2303                         }
2304                         else
2305                                 GL_AlphaToCoverage(false);
2306                 }
2307         }
2308         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2309         {
2310                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2311                 {
2312                         switch(rsurface.texture->offsetmapping)
2313                         {
2314                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2315                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317                         case OFFSETMAPPING_OFF: break;
2318                         }
2319                 }
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2321                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2323                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2324                 // directional model lighting
2325                 mode = SHADERMODE_LIGHTDIRECTION;
2326                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327                         permutation |= SHADERPERMUTATION_GLOW;
2328                 permutation |= SHADERPERMUTATION_DIFFUSE;
2329                 if (specularscale > 0)
2330                         permutation |= SHADERPERMUTATION_SPECULAR;
2331                 if (r_refdef.fogenabled)
2332                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2333                 if (rsurface.texture->colormapping)
2334                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2335                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2336                 {
2337                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2338                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2339
2340                         if (r_shadow_shadowmap2ddepthbuffer)
2341                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2342                 }
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2344                         permutation |= SHADERPERMUTATION_REFLECTION;
2345                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2346                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2347                 if (rsurface.texture->reflectmasktexture)
2348                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2349                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2350                 {
2351                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2352                         if (r_shadow_bouncegriddirectional)
2353                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2354                 }
2355                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2356                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 // when using alphatocoverage, we don't need alphakill
2358                 if (vid.allowalphatocoverage)
2359                 {
2360                         if (r_transparent_alphatocoverage.integer)
2361                         {
2362                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2363                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2364                         }
2365                         else
2366                                 GL_AlphaToCoverage(false);
2367                 }
2368         }
2369         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2370         {
2371                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2372                 {
2373                         switch(rsurface.texture->offsetmapping)
2374                         {
2375                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2376                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2377                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_OFF: break;
2379                         }
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2382                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2384                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2385                 // ambient model lighting
2386                 mode = SHADERMODE_LIGHTDIRECTION;
2387                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2388                         permutation |= SHADERPERMUTATION_GLOW;
2389                 if (r_refdef.fogenabled)
2390                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2391                 if (rsurface.texture->colormapping)
2392                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2393                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2394                 {
2395                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2396                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2397
2398                         if (r_shadow_shadowmap2ddepthbuffer)
2399                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2402                         permutation |= SHADERPERMUTATION_REFLECTION;
2403                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2404                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2405                 if (rsurface.texture->reflectmasktexture)
2406                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2407                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2408                 {
2409                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410                         if (r_shadow_bouncegriddirectional)
2411                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412                 }
2413                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 // when using alphatocoverage, we don't need alphakill
2416                 if (vid.allowalphatocoverage)
2417                 {
2418                         if (r_transparent_alphatocoverage.integer)
2419                         {
2420                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2421                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2422                         }
2423                         else
2424                                 GL_AlphaToCoverage(false);
2425                 }
2426         }
2427         else
2428         {
2429                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2430                 {
2431                         switch(rsurface.texture->offsetmapping)
2432                         {
2433                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2434                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_OFF: break;
2437                         }
2438                 }
2439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2440                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2442                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2443                 // lightmapped wall
2444                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2445                         permutation |= SHADERPERMUTATION_GLOW;
2446                 if (r_refdef.fogenabled)
2447                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2448                 if (rsurface.texture->colormapping)
2449                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2450                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2451                 {
2452                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2453                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2454
2455                         if (r_shadow_shadowmap2ddepthbuffer)
2456                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2457                 }
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459                         permutation |= SHADERPERMUTATION_REFLECTION;
2460                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462                 if (rsurface.texture->reflectmasktexture)
2463                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464                 if (FAKELIGHT_ENABLED)
2465                 {
2466                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2467                         mode = SHADERMODE_FAKELIGHT;
2468                         permutation |= SHADERPERMUTATION_DIFFUSE;
2469                         if (specularscale > 0)
2470                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471                 }
2472                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2473                 {
2474                         // deluxemapping (light direction texture)
2475                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2477                         else
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2479                         permutation |= SHADERPERMUTATION_DIFFUSE;
2480                         if (specularscale > 0)
2481                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482                 }
2483                 else if (r_glsl_deluxemapping.integer >= 2)
2484                 {
2485                         // fake deluxemapping (uniform light direction in tangentspace)
2486                         if (rsurface.uselightmaptexture)
2487                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2488                         else
2489                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2490                         permutation |= SHADERPERMUTATION_DIFFUSE;
2491                         if (specularscale > 0)
2492                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2493                 }
2494                 else if (rsurface.uselightmaptexture)
2495                 {
2496                         // ordinary lightmapping (q1bsp, q3bsp)
2497                         mode = SHADERMODE_LIGHTMAP;
2498                 }
2499                 else
2500                 {
2501                         // ordinary vertex coloring (q3bsp)
2502                         mode = SHADERMODE_VERTEXCOLOR;
2503                 }
2504                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2505                 {
2506                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2507                         if (r_shadow_bouncegriddirectional)
2508                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2509                 }
2510                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 // when using alphatocoverage, we don't need alphakill
2513                 if (vid.allowalphatocoverage)
2514                 {
2515                         if (r_transparent_alphatocoverage.integer)
2516                         {
2517                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2518                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2519                         }
2520                         else
2521                                 GL_AlphaToCoverage(false);
2522                 }
2523         }
2524         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2525                 colormod = dummy_colormod;
2526         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2527                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2528         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2529                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2530         switch(vid.renderpath)
2531         {
2532         case RENDERPATH_D3D9:
2533 #ifdef SUPPORTD3D
2534                 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);
2535                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2536                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2537                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2541                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_LIGHTDIRECTION)
2546                         {
2547                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2548                         }
2549                 }
2550                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2553                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2554                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2555
2556                 if (mode == SHADERMODE_LIGHTSOURCE)
2557                 {
2558                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2563
2564                         // additive passes are only darkened by fog, not tinted
2565                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2567                 }
2568                 else
2569                 {
2570                         if (mode == SHADERMODE_FLATCOLOR)
2571                         {
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2573                         }
2574                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2575                         {
2576                                 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]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[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], colormod[1], colormod[2]);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2583                         }
2584                         else
2585                         {
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2588                                 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);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2591                         }
2592                         // additive passes are only darkened by fog, not tinted
2593                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2595                         else
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2597                         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);
2598                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605                         if (mode == SHADERMODE_WATER)
2606                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2607                 }
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2609                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2610                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2611                 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));
2612                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2613                 if (rsurface.texture->pantstexture)
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2615                 else
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2617                 if (rsurface.texture->shirttexture)
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2619                 else
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2621                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2626                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2627                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2630                         );
2631                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2632                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2633                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2634                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2635
2636                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2637                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2638                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2639                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2644                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2645                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2646                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2647                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2648                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2649                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2650                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2651                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2652                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2653                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2654                 {
2655                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2656                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2657                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2658                 }
2659                 else
2660                 {
2661                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2662                 }
2663 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2664                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2666                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2667                 {
2668                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2669                         if (rsurface.rtlight)
2670                         {
2671                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2672                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2673                         }
2674                 }
2675 #endif
2676                 break;
2677         case RENDERPATH_D3D10:
2678                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2679                 break;
2680         case RENDERPATH_D3D11:
2681                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2682                 break;
2683         case RENDERPATH_GL20:
2684         case RENDERPATH_GLES2:
2685                 if (!vid.useinterleavedarrays)
2686                 {
2687                         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);
2688                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2689                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2690                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2695                 }
2696                 else
2697                 {
2698                         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);
2699                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2700                 }
2701                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2702                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2703                 if (mode == SHADERMODE_LIGHTSOURCE)
2704                 {
2705                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2706                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2707                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2708                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2709                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2710                         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);
2711         
2712                         // additive passes are only darkened by fog, not tinted
2713                         if (r_glsl_permutation->loc_FogColor >= 0)
2714                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2715                         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);
2716                 }
2717                 else
2718                 {
2719                         if (mode == SHADERMODE_FLATCOLOR)
2720                         {
2721                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2722                         }
2723                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2724                         {
2725                                 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]);
2726                                 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]);
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], colormod[1], colormod[2]);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2730                                 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]);
2731                                 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]);
2732                         }
2733                         else
2734                         {
2735                                 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]);
2736                                 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]);
2737                                 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);
2738                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2740                         }
2741                         // additive passes are only darkened by fog, not tinted
2742                         if (r_glsl_permutation->loc_FogColor >= 0)
2743                         {
2744                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2746                                 else
2747                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748                         }
2749                         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);
2750                         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]);
2751                         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]);
2752                         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]);
2753                         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]);
2754                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2755                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2756                         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);
2757                         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]);
2758                 }
2759                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2760                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2762                 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]);
2763                 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]);
2764
2765                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2766                 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));
2767                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2768                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2769                 {
2770                         if (rsurface.texture->pantstexture)
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2772                         else
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2774                 }
2775                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2776                 {
2777                         if (rsurface.texture->shirttexture)
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2779                         else
2780                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2781                 }
2782                 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]);
2783                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2784                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2785                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2786                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2787                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2788                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2791                         );
2792                 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);
2793                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2794                 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]);
2795                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2796                 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);}
2797                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2798
2799                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2800                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2801                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2802                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2803                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2804                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2805                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2810                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2811                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2812                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2813                 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);
2814                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2815                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2816                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2817                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2818                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2819                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2820                 {
2821                         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);
2822                         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);
2823                         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);
2824                 }
2825                 else
2826                 {
2827                         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);
2828                 }
2829                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2830                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2831                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2832                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2833                 {
2834                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2835                         if (rsurface.rtlight)
2836                         {
2837                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2838                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2839                         }
2840                 }
2841                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2842                 CHECKGLERROR
2843                 break;
2844         case RENDERPATH_GL11:
2845         case RENDERPATH_GL13:
2846         case RENDERPATH_GLES1:
2847                 break;
2848         case RENDERPATH_SOFT:
2849                 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);
2850                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2851                 R_SetupShader_SetPermutationSoft(mode, permutation);
2852                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2853                 if (mode == SHADERMODE_LIGHTSOURCE)
2854                 {
2855                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2861         
2862                         // additive passes are only darkened by fog, not tinted
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2865                 }
2866                 else
2867                 {
2868                         if (mode == SHADERMODE_FLATCOLOR)
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2871                         }
2872                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2873                         {
2874                                 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]);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[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], colormod[1], colormod[2]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2879                                 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]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2881                         }
2882                         else
2883                         {
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2886                                 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);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2889                         }
2890                         // additive passes are only darkened by fog, not tinted
2891                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2895                         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);
2896                         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]);
2897                         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]);
2898                         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]);
2899                         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]);
2900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2903                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2904                 }
2905                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2908                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2909                 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]);
2910
2911                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2912                 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));
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2914                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2915                 {
2916                         if (rsurface.texture->pantstexture)
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2918                         else
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2920                 }
2921                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2922                 {
2923                         if (rsurface.texture->shirttexture)
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2925                         else
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2927                 }
2928                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2932                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2933                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2934                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2937                         );
2938                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2940                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2942
2943                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2944                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2945                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2946                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2947                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2951                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2953                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2955                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2956                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2957                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2958                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2959                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2960                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2961                 {
2962                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2963                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2964                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2965                 }
2966                 else
2967                 {
2968                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2969                 }
2970 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2971                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2973                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2974                 {
2975                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2976                         if (rsurface.rtlight)
2977                         {
2978                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2979                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2980                         }
2981                 }
2982                 break;
2983         }
2984 }
2985
2986 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2987 {
2988         // select a permutation of the lighting shader appropriate to this
2989         // combination of texture, entity, light source, and fogging, only use the
2990         // minimum features necessary to avoid wasting rendering time in the
2991         // fragment shader on features that are not being used
2992         unsigned int permutation = 0;
2993         unsigned int mode = 0;
2994         const float *lightcolorbase = rtlight->currentcolor;
2995         float ambientscale = rtlight->ambientscale;
2996         float diffusescale = rtlight->diffusescale;
2997         float specularscale = rtlight->specularscale;
2998         // this is the location of the light in view space
2999         vec3_t viewlightorigin;
3000         // this transforms from view space (camera) to light space (cubemap)
3001         matrix4x4_t viewtolight;
3002         matrix4x4_t lighttoview;
3003         float viewtolight16f[16];
3004         // light source
3005         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3006         if (rtlight->currentcubemap != r_texture_whitecube)
3007                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3008         if (diffusescale > 0)
3009                 permutation |= SHADERPERMUTATION_DIFFUSE;
3010         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3011                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3012         if (r_shadow_usingshadowmap2d)
3013         {
3014                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3015                 if (r_shadow_shadowmapvsdct)
3016                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3017
3018                 if (r_shadow_shadowmap2ddepthbuffer)
3019                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3020         }
3021         if (vid.allowalphatocoverage)
3022                 GL_AlphaToCoverage(false);
3023         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3024         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3025         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3026         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3027         switch(vid.renderpath)
3028         {
3029         case RENDERPATH_D3D9:
3030 #ifdef SUPPORTD3D
3031                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3032                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3033                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3037                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3038                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3039                 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);
3040                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3042
3043                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3044                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3045                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3046                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3047                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3048 #endif
3049                 break;
3050         case RENDERPATH_D3D10:
3051                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3052                 break;
3053         case RENDERPATH_D3D11:
3054                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3055                 break;
3056         case RENDERPATH_GL20:
3057         case RENDERPATH_GLES2:
3058                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3059                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3061                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3062                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3064                 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]);
3065                 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]);
3066                 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);
3067                 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]);
3068                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3069
3070                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3071                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3073                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3074                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3075                 break;
3076         case RENDERPATH_GL11:
3077         case RENDERPATH_GL13:
3078         case RENDERPATH_GLES1:
3079                 break;
3080         case RENDERPATH_SOFT:
3081                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3082                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3083                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3087                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3088                 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]);
3089                 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);
3090                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3091                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3092
3093                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3094                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3095                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3096                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3097                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3098                 break;
3099         }
3100 }
3101
3102 #define SKINFRAME_HASH 1024
3103
3104 typedef struct
3105 {
3106         int loadsequence; // incremented each level change
3107         memexpandablearray_t array;
3108         skinframe_t *hash[SKINFRAME_HASH];
3109 }
3110 r_skinframe_t;
3111 r_skinframe_t r_skinframe;
3112
3113 void R_SkinFrame_PrepareForPurge(void)
3114 {
3115         r_skinframe.loadsequence++;
3116         // wrap it without hitting zero
3117         if (r_skinframe.loadsequence >= 200)
3118                 r_skinframe.loadsequence = 1;
3119 }
3120
3121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3122 {
3123         if (!skinframe)
3124                 return;
3125         // mark the skinframe as used for the purging code
3126         skinframe->loadsequence = r_skinframe.loadsequence;
3127 }
3128
3129 void R_SkinFrame_Purge(void)
3130 {
3131         int i;
3132         skinframe_t *s;
3133         for (i = 0;i < SKINFRAME_HASH;i++)
3134         {
3135                 for (s = r_skinframe.hash[i];s;s = s->next)
3136                 {
3137                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3138                         {
3139                                 if (s->merged == s->base)
3140                                         s->merged = NULL;
3141                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3142                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3143                                 R_PurgeTexture(s->merged);s->merged = NULL;
3144                                 R_PurgeTexture(s->base  );s->base   = NULL;
3145                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3146                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3147                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3148                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3149                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3150                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3151                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3152                                 s->loadsequence = 0;
3153                         }
3154                 }
3155         }
3156 }
3157
3158 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3159         skinframe_t *item;
3160         char basename[MAX_QPATH];
3161
3162         Image_StripImageExtension(name, basename, sizeof(basename));
3163
3164         if( last == NULL ) {
3165                 int hashindex;
3166                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167                 item = r_skinframe.hash[hashindex];
3168         } else {
3169                 item = last->next;
3170         }
3171
3172         // linearly search through the hash bucket
3173         for( ; item ; item = item->next ) {
3174                 if( !strcmp( item->basename, basename ) ) {
3175                         return item;
3176                 }
3177         }
3178         return NULL;
3179 }
3180
3181 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3182 {
3183         skinframe_t *item;
3184         int hashindex;
3185         char basename[MAX_QPATH];
3186
3187         Image_StripImageExtension(name, basename, sizeof(basename));
3188
3189         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3190         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3191                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3192                         break;
3193
3194         if (!item) {
3195                 rtexture_t *dyntexture;
3196                 // check whether its a dynamic texture
3197                 dyntexture = CL_GetDynTexture( basename );
3198                 if (!add && !dyntexture)
3199                         return NULL;
3200                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3201                 memset(item, 0, sizeof(*item));
3202                 strlcpy(item->basename, basename, sizeof(item->basename));
3203                 item->base = dyntexture; // either NULL or dyntexture handle
3204                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3205                 item->comparewidth = comparewidth;
3206                 item->compareheight = compareheight;
3207                 item->comparecrc = comparecrc;
3208                 item->next = r_skinframe.hash[hashindex];
3209                 r_skinframe.hash[hashindex] = item;
3210         }
3211         else if (textureflags & TEXF_FORCE_RELOAD)
3212         {
3213                 rtexture_t *dyntexture;
3214                 // check whether its a dynamic texture
3215                 dyntexture = CL_GetDynTexture( basename );
3216                 if (!add && !dyntexture)
3217                         return NULL;
3218                 if (item->merged == item->base)
3219                         item->merged = NULL;
3220                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3221                 R_PurgeTexture(item->stain );item->stain  = NULL;
3222                 R_PurgeTexture(item->merged);item->merged = NULL;
3223                 R_PurgeTexture(item->base  );item->base   = NULL;
3224                 R_PurgeTexture(item->pants );item->pants  = NULL;
3225                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3226                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3227                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3228                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3229                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3230         R_PurgeTexture(item->reflect);item->reflect = NULL;
3231                 item->loadsequence = 0;
3232         }
3233         else if( item->base == NULL )
3234         {
3235                 rtexture_t *dyntexture;
3236                 // check whether its a dynamic texture
3237                 // 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]
3238                 dyntexture = CL_GetDynTexture( basename );
3239                 item->base = dyntexture; // either NULL or dyntexture handle
3240         }
3241
3242         R_SkinFrame_MarkUsed(item);
3243         return item;
3244 }
3245
3246 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3247         { \
3248                 unsigned long long avgcolor[5], wsum; \
3249                 int pix, comp, w; \
3250                 avgcolor[0] = 0; \
3251                 avgcolor[1] = 0; \
3252                 avgcolor[2] = 0; \
3253                 avgcolor[3] = 0; \
3254                 avgcolor[4] = 0; \
3255                 wsum = 0; \
3256                 for(pix = 0; pix < cnt; ++pix) \
3257                 { \
3258                         w = 0; \
3259                         for(comp = 0; comp < 3; ++comp) \
3260                                 w += getpixel; \
3261                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3262                         { \
3263                                 ++wsum; \
3264                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3265                                 w = getpixel; \
3266                                 for(comp = 0; comp < 3; ++comp) \
3267                                         avgcolor[comp] += getpixel * w; \
3268                                 avgcolor[3] += w; \
3269                         } \
3270                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3271                         avgcolor[4] += getpixel; \
3272                 } \
3273                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3274                         avgcolor[3] = 1; \
3275                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3276                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3277                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3278                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3279         }
3280
3281 extern cvar_t gl_picmip;
3282 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3283 {
3284         int j;
3285         unsigned char *pixels;
3286         unsigned char *bumppixels;
3287         unsigned char *basepixels = NULL;
3288         int basepixels_width = 0;
3289         int basepixels_height = 0;
3290         skinframe_t *skinframe;
3291         rtexture_t *ddsbase = NULL;
3292         qboolean ddshasalpha = false;
3293         float ddsavgcolor[4];
3294         char basename[MAX_QPATH];
3295         int miplevel = R_PicmipForFlags(textureflags);
3296         int savemiplevel = miplevel;
3297         int mymiplevel;
3298         char vabuf[1024];
3299
3300         if (cls.state == ca_dedicated)
3301                 return NULL;
3302
3303         // return an existing skinframe if already loaded
3304         // if loading of the first image fails, don't make a new skinframe as it
3305         // would cause all future lookups of this to be missing
3306         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3307         if (skinframe && skinframe->base)
3308                 return skinframe;
3309
3310         Image_StripImageExtension(name, basename, sizeof(basename));
3311
3312         // check for DDS texture file first
3313         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3314         {
3315                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3316                 if (basepixels == NULL)
3317                         return NULL;
3318         }
3319
3320         // FIXME handle miplevel
3321
3322         if (developer_loading.integer)
3323                 Con_Printf("loading skin \"%s\"\n", name);
3324
3325         // we've got some pixels to store, so really allocate this new texture now
3326         if (!skinframe)
3327                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3328         textureflags &= ~TEXF_FORCE_RELOAD;
3329         skinframe->stain = NULL;
3330         skinframe->merged = NULL;
3331         skinframe->base = NULL;
3332         skinframe->pants = NULL;
3333         skinframe->shirt = NULL;
3334         skinframe->nmap = NULL;
3335         skinframe->gloss = NULL;
3336         skinframe->glow = NULL;
3337         skinframe->fog = NULL;
3338         skinframe->reflect = NULL;
3339         skinframe->hasalpha = false;
3340
3341         if (ddsbase)
3342         {
3343                 skinframe->base = ddsbase;
3344                 skinframe->hasalpha = ddshasalpha;
3345                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3346                 if (r_loadfog && skinframe->hasalpha)
3347                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3348                 //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]);
3349         }
3350         else
3351         {
3352                 basepixels_width = image_width;
3353                 basepixels_height = image_height;
3354                 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);
3355                 if (textureflags & TEXF_ALPHA)
3356                 {
3357                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3358                         {
3359                                 if (basepixels[j] < 255)
3360                                 {
3361                                         skinframe->hasalpha = true;
3362                                         break;
3363                                 }
3364                         }
3365                         if (r_loadfog && skinframe->hasalpha)
3366                         {
3367                                 // has transparent pixels
3368                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3369                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3370                                 {
3371                                         pixels[j+0] = 255;
3372                                         pixels[j+1] = 255;
3373                                         pixels[j+2] = 255;
3374                                         pixels[j+3] = basepixels[j+3];
3375                                 }
3376                                 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);
3377                                 Mem_Free(pixels);
3378                         }
3379                 }
3380                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3381 #ifndef USE_GLES2
3382                 //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]);
3383                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3384                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3385                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3386                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3387 #endif
3388         }
3389
3390         if (r_loaddds)
3391         {
3392                 mymiplevel = savemiplevel;
3393                 if (r_loadnormalmap)
3394                         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);
3395                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3396                 if (r_loadgloss)
3397                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3398                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3399                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3400                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3401         }
3402
3403         // _norm is the name used by tenebrae and has been adopted as standard
3404         if (r_loadnormalmap && skinframe->nmap == NULL)
3405         {
3406                 mymiplevel = savemiplevel;
3407                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3408                 {
3409                         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);
3410                         Mem_Free(pixels);
3411                         pixels = NULL;
3412                 }
3413                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3414                 {
3415                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3416                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3417                         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);
3418                         Mem_Free(pixels);
3419                         Mem_Free(bumppixels);
3420                 }
3421                 else if (r_shadow_bumpscale_basetexture.value > 0)
3422                 {
3423                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3424                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3425                         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);
3426                         Mem_Free(pixels);
3427                 }
3428 #ifndef USE_GLES2
3429                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3430                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3431 #endif
3432         }
3433
3434         // _luma is supported only for tenebrae compatibility
3435         // _glow is the preferred name
3436         mymiplevel = savemiplevel;
3437         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))))
3438         {
3439                 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);
3440 #ifndef USE_GLES2
3441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3442                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3443 #endif
3444                 Mem_Free(pixels);pixels = NULL;
3445         }
3446
3447         mymiplevel = savemiplevel;
3448         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3449         {
3450                 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);
3451 #ifndef USE_GLES2
3452                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3453                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3454 #endif
3455                 Mem_Free(pixels);
3456                 pixels = NULL;
3457         }
3458
3459         mymiplevel = savemiplevel;
3460         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3461         {
3462                 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);
3463 #ifndef USE_GLES2
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3465                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3466 #endif
3467                 Mem_Free(pixels);
3468                 pixels = NULL;
3469         }
3470
3471         mymiplevel = savemiplevel;
3472         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3473         {
3474                 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);
3475 #ifndef USE_GLES2
3476                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3477                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3478 #endif
3479                 Mem_Free(pixels);
3480                 pixels = NULL;
3481         }
3482
3483         mymiplevel = savemiplevel;
3484         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3485         {
3486                 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);
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3489                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3490 #endif
3491                 Mem_Free(pixels);
3492                 pixels = NULL;
3493         }
3494
3495         if (basepixels)
3496                 Mem_Free(basepixels);
3497
3498         return skinframe;
3499 }
3500
3501 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3502 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3503 {
3504         int i;
3505         unsigned char *temp1, *temp2;
3506         skinframe_t *skinframe;
3507         char vabuf[1024];
3508
3509         if (cls.state == ca_dedicated)
3510                 return NULL;
3511
3512         // if already loaded just return it, otherwise make a new skinframe
3513         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3514         if (skinframe && skinframe->base)
3515                 return skinframe;
3516         textureflags &= ~TEXF_FORCE_RELOAD;
3517
3518         skinframe->stain = NULL;
3519         skinframe->merged = NULL;
3520         skinframe->base = NULL;
3521         skinframe->pants = NULL;
3522         skinframe->shirt = NULL;
3523         skinframe->nmap = NULL;
3524         skinframe->gloss = NULL;
3525         skinframe->glow = NULL;
3526         skinframe->fog = NULL;
3527         skinframe->reflect = NULL;
3528         skinframe->hasalpha = false;
3529
3530         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3531         if (!skindata)
3532                 return NULL;
3533
3534         if (developer_loading.integer)
3535                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3536
3537         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3538         {
3539                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3540                 temp2 = temp1 + width * height * 4;
3541                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3542                 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);
3543                 Mem_Free(temp1);
3544         }
3545         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3546         if (textureflags & TEXF_ALPHA)
3547         {
3548                 for (i = 3;i < width * height * 4;i += 4)
3549                 {
3550                         if (skindata[i] < 255)
3551                         {
3552                                 skinframe->hasalpha = true;
3553                                 break;
3554                         }
3555                 }
3556                 if (r_loadfog && skinframe->hasalpha)
3557                 {
3558                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3559                         memcpy(fogpixels, skindata, width * height * 4);
3560                         for (i = 0;i < width * height * 4;i += 4)
3561                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3562                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3563                         Mem_Free(fogpixels);
3564                 }
3565         }
3566
3567         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3568         //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]);
3569
3570         return skinframe;
3571 }
3572
3573 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3574 {
3575         int i;
3576         int featuresmask;
3577         skinframe_t *skinframe;
3578
3579         if (cls.state == ca_dedicated)
3580                 return NULL;
3581
3582         // if already loaded just return it, otherwise make a new skinframe
3583         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3584         if (skinframe && skinframe->base)
3585                 return skinframe;
3586         textureflags &= ~TEXF_FORCE_RELOAD;
3587
3588         skinframe->stain = NULL;
3589         skinframe->merged = NULL;
3590         skinframe->base = NULL;
3591         skinframe->pants = NULL;
3592         skinframe->shirt = NULL;
3593         skinframe->nmap = NULL;
3594         skinframe->gloss = NULL;
3595         skinframe->glow = NULL;
3596         skinframe->fog = NULL;
3597         skinframe->reflect = NULL;
3598         skinframe->hasalpha = false;
3599
3600         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3601         if (!skindata)
3602                 return NULL;
3603
3604         if (developer_loading.integer)
3605                 Con_Printf("loading quake skin \"%s\"\n", name);
3606
3607         // 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)
3608         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3609         memcpy(skinframe->qpixels, skindata, width*height);
3610         skinframe->qwidth = width;
3611         skinframe->qheight = height;
3612
3613         featuresmask = 0;
3614         for (i = 0;i < width * height;i++)
3615                 featuresmask |= palette_featureflags[skindata[i]];
3616
3617         skinframe->hasalpha = false;
3618         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3619         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3620         skinframe->qgeneratemerged = true;
3621         skinframe->qgeneratebase = skinframe->qhascolormapping;
3622         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3623
3624         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3625         //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]);
3626
3627         return skinframe;
3628 }
3629
3630 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3631 {
3632         int width;
3633         int height;
3634         unsigned char *skindata;
3635         char vabuf[1024];
3636
3637         if (!skinframe->qpixels)
3638                 return;
3639
3640         if (!skinframe->qhascolormapping)
3641                 colormapped = false;
3642
3643         if (colormapped)
3644         {
3645                 if (!skinframe->qgeneratebase)
3646                         return;
3647         }
3648         else
3649         {
3650                 if (!skinframe->qgeneratemerged)
3651                         return;
3652         }
3653
3654         width = skinframe->qwidth;
3655         height = skinframe->qheight;
3656         skindata = skinframe->qpixels;
3657
3658         if (skinframe->qgeneratenmap)
3659         {
3660                 unsigned char *temp1, *temp2;
3661                 skinframe->qgeneratenmap = false;
3662                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3663                 temp2 = temp1 + width * height * 4;
3664                 // use either a custom palette or the quake palette
3665                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3666                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3667                 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);
3668                 Mem_Free(temp1);
3669         }
3670
3671         if (skinframe->qgenerateglow)
3672         {
3673                 skinframe->qgenerateglow = false;
3674                 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
3675         }
3676
3677         if (colormapped)
3678         {
3679                 skinframe->qgeneratebase = false;
3680                 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);
3681                 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);
3682                 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);
3683         }
3684         else
3685         {
3686                 skinframe->qgeneratemerged = false;
3687                 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);
3688         }
3689
3690         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3691         {
3692                 Mem_Free(skinframe->qpixels);
3693                 skinframe->qpixels = NULL;
3694         }
3695 }
3696
3697 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)
3698 {
3699         int i;
3700         skinframe_t *skinframe;
3701         char vabuf[1024];
3702
3703         if (cls.state == ca_dedicated)
3704                 return NULL;
3705
3706         // if already loaded just return it, otherwise make a new skinframe
3707         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3708         if (skinframe && skinframe->base)
3709                 return skinframe;
3710         textureflags &= ~TEXF_FORCE_RELOAD;
3711
3712         skinframe->stain = NULL;
3713         skinframe->merged = NULL;
3714         skinframe->base = NULL;
3715         skinframe->pants = NULL;
3716         skinframe->shirt = NULL;
3717         skinframe->nmap = NULL;
3718         skinframe->gloss = NULL;
3719         skinframe->glow = NULL;
3720         skinframe->fog = NULL;
3721         skinframe->reflect = NULL;
3722         skinframe->hasalpha = false;
3723
3724         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3725         if (!skindata)
3726                 return NULL;
3727
3728         if (developer_loading.integer)
3729                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3730
3731         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3732         if (textureflags & TEXF_ALPHA)
3733         {
3734                 for (i = 0;i < width * height;i++)
3735                 {
3736                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3737                         {
3738                                 skinframe->hasalpha = true;
3739                                 break;
3740                         }
3741                 }
3742                 if (r_loadfog && skinframe->hasalpha)
3743                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3744         }
3745
3746         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3747         //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]);
3748
3749         return skinframe;
3750 }
3751
3752 skinframe_t *R_SkinFrame_LoadMissing(void)
3753 {
3754         skinframe_t *skinframe;
3755
3756         if (cls.state == ca_dedicated)
3757                 return NULL;
3758
3759         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3760         skinframe->stain = NULL;
3761         skinframe->merged = NULL;
3762         skinframe->base = NULL;
3763         skinframe->pants = NULL;
3764         skinframe->shirt = NULL;
3765         skinframe->nmap = NULL;
3766         skinframe->gloss = NULL;
3767         skinframe->glow = NULL;
3768         skinframe->fog = NULL;
3769         skinframe->reflect = NULL;
3770         skinframe->hasalpha = false;
3771
3772         skinframe->avgcolor[0] = rand() / RAND_MAX;
3773         skinframe->avgcolor[1] = rand() / RAND_MAX;
3774         skinframe->avgcolor[2] = rand() / RAND_MAX;
3775         skinframe->avgcolor[3] = 1;
3776
3777         return skinframe;
3778 }
3779
3780 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3781 typedef struct suffixinfo_s
3782 {
3783         const char *suffix;
3784         qboolean flipx, flipy, flipdiagonal;
3785 }
3786 suffixinfo_t;
3787 static suffixinfo_t suffix[3][6] =
3788 {
3789         {
3790                 {"px",   false, false, false},
3791                 {"nx",   false, false, false},
3792                 {"py",   false, false, false},
3793                 {"ny",   false, false, false},
3794                 {"pz",   false, false, false},
3795                 {"nz",   false, false, false}
3796         },
3797         {
3798                 {"posx", false, false, false},
3799                 {"negx", false, false, false},
3800                 {"posy", false, false, false},
3801                 {"negy", false, false, false},
3802                 {"posz", false, false, false},
3803                 {"negz", false, false, false}
3804         },
3805         {
3806                 {"rt",    true, false,  true},
3807                 {"lf",   false,  true,  true},
3808                 {"ft",    true,  true, false},
3809                 {"bk",   false, false, false},
3810                 {"up",    true, false,  true},
3811                 {"dn",    true, false,  true}
3812         }
3813 };
3814
3815 static int componentorder[4] = {0, 1, 2, 3};
3816
3817 static rtexture_t *R_LoadCubemap(const char *basename)
3818 {
3819         int i, j, cubemapsize;
3820         unsigned char *cubemappixels, *image_buffer;
3821         rtexture_t *cubemaptexture;
3822         char name[256];
3823         // must start 0 so the first loadimagepixels has no requested width/height
3824         cubemapsize = 0;
3825         cubemappixels = NULL;
3826         cubemaptexture = NULL;
3827         // keep trying different suffix groups (posx, px, rt) until one loads
3828         for (j = 0;j < 3 && !cubemappixels;j++)
3829         {
3830                 // load the 6 images in the suffix group
3831                 for (i = 0;i < 6;i++)
3832                 {
3833                         // generate an image name based on the base and and suffix
3834                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3835                         // load it
3836                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3837                         {
3838                                 // an image loaded, make sure width and height are equal
3839                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3840                                 {
3841                                         // if this is the first image to load successfully, allocate the cubemap memory
3842                                         if (!cubemappixels && image_width >= 1)
3843                                         {
3844                                                 cubemapsize = image_width;
3845                                                 // note this clears to black, so unavailable sides are black
3846                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3847                                         }
3848                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3849                                         if (cubemappixels)
3850                                                 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);
3851                                 }
3852                                 else
3853                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3854                                 // free the image
3855                                 Mem_Free(image_buffer);
3856                         }
3857                 }
3858         }
3859         // if a cubemap loaded, upload it
3860         if (cubemappixels)
3861         {
3862                 if (developer_loading.integer)
3863                         Con_Printf("loading cubemap \"%s\"\n", basename);
3864
3865                 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);
3866                 Mem_Free(cubemappixels);
3867         }
3868         else
3869         {
3870                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3871                 if (developer_loading.integer)
3872                 {
3873                         Con_Printf("(tried tried images ");
3874                         for (j = 0;j < 3;j++)
3875                                 for (i = 0;i < 6;i++)
3876                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3877                         Con_Print(" and was unable to find any of them).\n");
3878                 }
3879         }
3880         return cubemaptexture;
3881 }
3882
3883 rtexture_t *R_GetCubemap(const char *basename)
3884 {
3885         int i;
3886         for (i = 0;i < r_texture_numcubemaps;i++)
3887                 if (r_texture_cubemaps[i] != NULL)
3888                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3889                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3890         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3891                 return r_texture_whitecube;
3892         r_texture_numcubemaps++;
3893         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3894         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3895         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3896         return r_texture_cubemaps[i]->texture;
3897 }
3898
3899 static void R_Main_FreeViewCache(void)
3900 {
3901         if (r_refdef.viewcache.entityvisible)
3902                 Mem_Free(r_refdef.viewcache.entityvisible);
3903         if (r_refdef.viewcache.world_pvsbits)
3904                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3905         if (r_refdef.viewcache.world_leafvisible)
3906                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3907         if (r_refdef.viewcache.world_surfacevisible)
3908                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3909         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3910 }
3911
3912 static void R_Main_ResizeViewCache(void)
3913 {
3914         int numentities = r_refdef.scene.numentities;
3915         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3916         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3917         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3918         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3919         if (r_refdef.viewcache.maxentities < numentities)
3920         {
3921                 r_refdef.viewcache.maxentities = numentities;
3922                 if (r_refdef.viewcache.entityvisible)
3923                         Mem_Free(r_refdef.viewcache.entityvisible);
3924                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3925         }
3926         if (r_refdef.viewcache.world_numclusters != numclusters)
3927         {
3928                 r_refdef.viewcache.world_numclusters = numclusters;
3929                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3930                 if (r_refdef.viewcache.world_pvsbits)
3931                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3932                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3933         }
3934         if (r_refdef.viewcache.world_numleafs != numleafs)
3935         {
3936                 r_refdef.viewcache.world_numleafs = numleafs;
3937                 if (r_refdef.viewcache.world_leafvisible)
3938                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3939                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3940         }
3941         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3942         {
3943                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3944                 if (r_refdef.viewcache.world_surfacevisible)
3945                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3946                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3947         }
3948 }
3949
3950 extern rtexture_t *loadingscreentexture;
3951 static void gl_main_start(void)
3952 {
3953         loadingscreentexture = NULL;
3954         r_texture_blanknormalmap = NULL;
3955         r_texture_white = NULL;
3956         r_texture_grey128 = NULL;
3957         r_texture_black = NULL;
3958         r_texture_whitecube = NULL;
3959         r_texture_normalizationcube = NULL;
3960         r_texture_fogattenuation = NULL;
3961         r_texture_fogheighttexture = NULL;
3962         r_texture_gammaramps = NULL;
3963         r_texture_numcubemaps = 0;
3964
3965         r_loaddds = r_texture_dds_load.integer != 0;
3966         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3967
3968         switch(vid.renderpath)
3969         {
3970         case RENDERPATH_GL20:
3971         case RENDERPATH_D3D9:
3972         case RENDERPATH_D3D10:
3973         case RENDERPATH_D3D11:
3974         case RENDERPATH_SOFT:
3975         case RENDERPATH_GLES2:
3976                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3977                 Cvar_SetValueQuick(&gl_combine, 1);
3978                 Cvar_SetValueQuick(&r_glsl, 1);
3979                 r_loadnormalmap = true;
3980                 r_loadgloss = true;
3981                 r_loadfog = false;
3982                 break;
3983         case RENDERPATH_GL13:
3984         case RENDERPATH_GLES1:
3985                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3986                 Cvar_SetValueQuick(&gl_combine, 1);
3987                 Cvar_SetValueQuick(&r_glsl, 0);
3988                 r_loadnormalmap = false;
3989                 r_loadgloss = false;
3990                 r_loadfog = true;
3991                 break;
3992         case RENDERPATH_GL11:
3993                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3994                 Cvar_SetValueQuick(&gl_combine, 0);
3995                 Cvar_SetValueQuick(&r_glsl, 0);
3996                 r_loadnormalmap = false;
3997                 r_loadgloss = false;
3998                 r_loadfog = true;
3999                 break;
4000         }
4001
4002         R_AnimCache_Free();
4003         R_FrameData_Reset();
4004
4005         r_numqueries = 0;
4006         r_maxqueries = 0;
4007         memset(r_queries, 0, sizeof(r_queries));
4008
4009         r_qwskincache = NULL;
4010         r_qwskincache_size = 0;
4011
4012         // due to caching of texture_t references, the collision cache must be reset
4013         Collision_Cache_Reset(true);
4014
4015         // set up r_skinframe loading system for textures
4016         memset(&r_skinframe, 0, sizeof(r_skinframe));
4017         r_skinframe.loadsequence = 1;
4018         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4019
4020         r_main_texturepool = R_AllocTexturePool();
4021         R_BuildBlankTextures();
4022         R_BuildNoTexture();
4023         if (vid.support.arb_texture_cube_map)
4024         {
4025                 R_BuildWhiteCube();
4026                 R_BuildNormalizationCube();
4027         }
4028         r_texture_fogattenuation = NULL;
4029         r_texture_fogheighttexture = NULL;
4030         r_texture_gammaramps = NULL;
4031         //r_texture_fogintensity = NULL;
4032         memset(&r_fb, 0, sizeof(r_fb));
4033         r_glsl_permutation = NULL;
4034         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4035         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4036         glslshaderstring = NULL;
4037 #ifdef SUPPORTD3D
4038         r_hlsl_permutation = NULL;
4039         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4040         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4041 #endif
4042         hlslshaderstring = NULL;
4043         memset(&r_svbsp, 0, sizeof (r_svbsp));
4044
4045         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4046         r_texture_numcubemaps = 0;
4047
4048         r_refdef.fogmasktable_density = 0;
4049 }
4050
4051 static void gl_main_shutdown(void)
4052 {
4053         R_AnimCache_Free();
4054         R_FrameData_Reset();
4055
4056         R_Main_FreeViewCache();
4057
4058         switch(vid.renderpath)
4059         {
4060         case RENDERPATH_GL11:
4061         case RENDERPATH_GL13:
4062         case RENDERPATH_GL20:
4063         case RENDERPATH_GLES1:
4064         case RENDERPATH_GLES2:
4065 #ifdef GL_SAMPLES_PASSED_ARB
4066                 if (r_maxqueries)
4067                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4068 #endif
4069                 break;
4070         case RENDERPATH_D3D9:
4071                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4072                 break;
4073         case RENDERPATH_D3D10:
4074                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4075                 break;
4076         case RENDERPATH_D3D11:
4077                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4078                 break;
4079         case RENDERPATH_SOFT:
4080                 break;
4081         }
4082
4083         r_numqueries = 0;
4084         r_maxqueries = 0;
4085         memset(r_queries, 0, sizeof(r_queries));
4086
4087         r_qwskincache = NULL;
4088         r_qwskincache_size = 0;
4089
4090         // clear out the r_skinframe state
4091         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4092         memset(&r_skinframe, 0, sizeof(r_skinframe));
4093
4094         if (r_svbsp.nodes)
4095                 Mem_Free(r_svbsp.nodes);
4096         memset(&r_svbsp, 0, sizeof (r_svbsp));
4097         R_FreeTexturePool(&r_main_texturepool);
4098         loadingscreentexture = NULL;
4099         r_texture_blanknormalmap = NULL;
4100         r_texture_white = NULL;
4101         r_texture_grey128 = NULL;
4102         r_texture_black = NULL;
4103         r_texture_whitecube = NULL;
4104         r_texture_normalizationcube = NULL;
4105         r_texture_fogattenuation = NULL;
4106         r_texture_fogheighttexture = NULL;
4107         r_texture_gammaramps = NULL;
4108         r_texture_numcubemaps = 0;
4109         //r_texture_fogintensity = NULL;
4110         memset(&r_fb, 0, sizeof(r_fb));
4111         R_GLSL_Restart_f();
4112
4113         r_glsl_permutation = NULL;
4114         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4115         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4116         glslshaderstring = NULL;
4117 #ifdef SUPPORTD3D
4118         r_hlsl_permutation = NULL;
4119         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4120         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4121 #endif
4122         hlslshaderstring = NULL;
4123 }
4124
4125 static void gl_main_newmap(void)
4126 {
4127         // FIXME: move this code to client
4128         char *entities, entname[MAX_QPATH];
4129         if (r_qwskincache)
4130                 Mem_Free(r_qwskincache);
4131         r_qwskincache = NULL;
4132         r_qwskincache_size = 0;
4133         if (cl.worldmodel)
4134         {
4135                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4136                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4137                 {
4138                         CL_ParseEntityLump(entities);
4139                         Mem_Free(entities);
4140                         return;
4141                 }
4142                 if (cl.worldmodel->brush.entities)
4143                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4144         }
4145         R_Main_FreeViewCache();
4146
4147         R_FrameData_Reset();
4148 }
4149
4150 void GL_Main_Init(void)
4151 {
4152         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4153
4154         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4155         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4156         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4157         if (gamemode == GAME_NEHAHRA)
4158         {
4159                 Cvar_RegisterVariable (&gl_fogenable);
4160                 Cvar_RegisterVariable (&gl_fogdensity);
4161                 Cvar_RegisterVariable (&gl_fogred);
4162                 Cvar_RegisterVariable (&gl_foggreen);
4163                 Cvar_RegisterVariable (&gl_fogblue);
4164                 Cvar_RegisterVariable (&gl_fogstart);
4165                 Cvar_RegisterVariable (&gl_fogend);
4166                 Cvar_RegisterVariable (&gl_skyclip);
4167         }
4168         Cvar_RegisterVariable(&r_motionblur);
4169         Cvar_RegisterVariable(&r_damageblur);
4170         Cvar_RegisterVariable(&r_motionblur_averaging);
4171         Cvar_RegisterVariable(&r_motionblur_randomize);
4172         Cvar_RegisterVariable(&r_motionblur_minblur);
4173         Cvar_RegisterVariable(&r_motionblur_maxblur);
4174         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4175         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4176         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4177         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4178         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4179         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4180         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4181         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4182         Cvar_RegisterVariable(&r_equalize_entities_by);
4183         Cvar_RegisterVariable(&r_equalize_entities_to);
4184         Cvar_RegisterVariable(&r_depthfirst);
4185         Cvar_RegisterVariable(&r_useinfinitefarclip);
4186         Cvar_RegisterVariable(&r_farclip_base);
4187         Cvar_RegisterVariable(&r_farclip_world);
4188         Cvar_RegisterVariable(&r_nearclip);
4189         Cvar_RegisterVariable(&r_deformvertexes);
4190         Cvar_RegisterVariable(&r_transparent);
4191         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4192         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4193         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4194         Cvar_RegisterVariable(&r_showoverdraw);
4195         Cvar_RegisterVariable(&r_showbboxes);
4196         Cvar_RegisterVariable(&r_showsurfaces);
4197         Cvar_RegisterVariable(&r_showtris);
4198         Cvar_RegisterVariable(&r_shownormals);
4199         Cvar_RegisterVariable(&r_showlighting);
4200         Cvar_RegisterVariable(&r_showshadowvolumes);
4201         Cvar_RegisterVariable(&r_showcollisionbrushes);
4202         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4204         Cvar_RegisterVariable(&r_showdisabledepthtest);
4205         Cvar_RegisterVariable(&r_drawportals);
4206         Cvar_RegisterVariable(&r_drawentities);
4207         Cvar_RegisterVariable(&r_draw2d);
4208         Cvar_RegisterVariable(&r_drawworld);
4209         Cvar_RegisterVariable(&r_cullentities_trace);
4210         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4211         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4212         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4213         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4214         Cvar_RegisterVariable(&r_sortentities);
4215         Cvar_RegisterVariable(&r_drawviewmodel);
4216         Cvar_RegisterVariable(&r_drawexteriormodel);
4217         Cvar_RegisterVariable(&r_speeds);
4218         Cvar_RegisterVariable(&r_fullbrights);
4219         Cvar_RegisterVariable(&r_wateralpha);
4220         Cvar_RegisterVariable(&r_dynamic);
4221         Cvar_RegisterVariable(&r_fakelight);
4222         Cvar_RegisterVariable(&r_fakelight_intensity);
4223         Cvar_RegisterVariable(&r_fullbright);
4224         Cvar_RegisterVariable(&r_shadows);
4225         Cvar_RegisterVariable(&r_shadows_darken);
4226         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4227         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4228         Cvar_RegisterVariable(&r_shadows_throwdistance);
4229         Cvar_RegisterVariable(&r_shadows_throwdirection);
4230         Cvar_RegisterVariable(&r_shadows_focus);
4231         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4232         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4233         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4234         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4235         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4236         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4237         Cvar_RegisterVariable(&r_fog_exp2);
4238         Cvar_RegisterVariable(&r_fog_clear);
4239         Cvar_RegisterVariable(&r_drawfog);
4240         Cvar_RegisterVariable(&r_transparentdepthmasking);
4241         Cvar_RegisterVariable(&r_transparent_sortmindist);
4242         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4243         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4244         Cvar_RegisterVariable(&r_texture_dds_load);
4245         Cvar_RegisterVariable(&r_texture_dds_save);
4246         Cvar_RegisterVariable(&r_textureunits);
4247         Cvar_RegisterVariable(&gl_combine);
4248         Cvar_RegisterVariable(&r_usedepthtextures);
4249         Cvar_RegisterVariable(&r_viewfbo);
4250         Cvar_RegisterVariable(&r_viewscale);
4251         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4257         Cvar_RegisterVariable(&r_glsl);
4258         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4259         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4267         Cvar_RegisterVariable(&r_glsl_postprocess);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4276         Cvar_RegisterVariable(&r_celshading);
4277         Cvar_RegisterVariable(&r_celoutlines);
4278
4279         Cvar_RegisterVariable(&r_water);
4280         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4281         Cvar_RegisterVariable(&r_water_clippingplanebias);
4282         Cvar_RegisterVariable(&r_water_refractdistort);
4283         Cvar_RegisterVariable(&r_water_reflectdistort);
4284         Cvar_RegisterVariable(&r_water_scissormode);
4285         Cvar_RegisterVariable(&r_water_lowquality);
4286         Cvar_RegisterVariable(&r_water_hideplayer);
4287         Cvar_RegisterVariable(&r_water_fbo);
4288
4289         Cvar_RegisterVariable(&r_lerpsprites);
4290         Cvar_RegisterVariable(&r_lerpmodels);
4291         Cvar_RegisterVariable(&r_lerplightstyles);
4292         Cvar_RegisterVariable(&r_waterscroll);
4293         Cvar_RegisterVariable(&r_bloom);
4294         Cvar_RegisterVariable(&r_bloom_colorscale);
4295         Cvar_RegisterVariable(&r_bloom_brighten);
4296         Cvar_RegisterVariable(&r_bloom_blur);
4297         Cvar_RegisterVariable(&r_bloom_resolution);
4298         Cvar_RegisterVariable(&r_bloom_colorexponent);
4299         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4300         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4301         Cvar_RegisterVariable(&r_hdr_glowintensity);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4310         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4311         Cvar_RegisterVariable(&developer_texturelogging);
4312         Cvar_RegisterVariable(&gl_lightmaps);
4313         Cvar_RegisterVariable(&r_test);
4314         Cvar_RegisterVariable(&r_glsl_saturation);
4315         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4316         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4317         Cvar_RegisterVariable(&r_framedatasize);
4318         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4319                 Cvar_SetValue("r_fullbrights", 0);
4320         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4321 }
4322
4323 void Render_Init(void)
4324 {
4325         gl_backend_init();
4326         R_Textures_Init();
4327         GL_Main_Init();
4328         Font_Init();
4329         GL_Draw_Init();
4330         R_Shadow_Init();
4331         R_Sky_Init();
4332         GL_Surf_Init();
4333         Sbar_Init();
4334         R_Particles_Init();
4335         R_Explosion_Init();
4336         R_LightningBeams_Init();
4337         Mod_RenderInit();
4338 }
4339
4340 /*
4341 ===============
4342 GL_Init
4343 ===============
4344 */
4345 #ifndef USE_GLES2
4346 extern char *ENGINE_EXTENSIONS;
4347 void GL_Init (void)
4348 {
4349         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4350         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4351         gl_version = (const char *)qglGetString(GL_VERSION);
4352         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4353
4354         if (!gl_extensions)
4355                 gl_extensions = "";
4356         if (!gl_platformextensions)
4357                 gl_platformextensions = "";
4358
4359         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4360         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4361         Con_Printf("GL_VERSION: %s\n", gl_version);
4362         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4363         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4364
4365         VID_CheckExtensions();
4366
4367         // LordHavoc: report supported extensions
4368         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4369
4370         // clear to black (loading plaque will be seen over this)
4371         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4372 }
4373 #endif
4374
4375 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4376 {
4377         int i;
4378         mplane_t *p;
4379         if (r_trippy.integer)
4380                 return false;
4381         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4382         {
4383                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4384                 if (i == 4)
4385                         continue;
4386                 p = r_refdef.view.frustum + i;
4387                 switch(p->signbits)
4388                 {
4389                 default:
4390                 case 0:
4391                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 1:
4395                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 2:
4399                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 3:
4403                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 4:
4407                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 5:
4411                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 6:
4415                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 7:
4419                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 }
4423         }
4424         return false;
4425 }
4426
4427 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4428 {
4429         int i;
4430         const mplane_t *p;
4431         if (r_trippy.integer)
4432                 return false;
4433         for (i = 0;i < numplanes;i++)
4434         {
4435                 p = planes + i;
4436                 switch(p->signbits)
4437                 {
4438                 default:
4439                 case 0:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 1:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 2:
4448                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 3:
4452                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 4:
4456                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 5:
4460                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 6:
4464                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 7:
4468                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 }
4472         }
4473         return false;
4474 }
4475
4476 //==================================================================================
4477
4478 // LordHavoc: this stores temporary data used within the same frame
4479
4480 typedef struct r_framedata_mem_s
4481 {
4482         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4483         size_t size; // how much usable space
4484         size_t current; // how much space in use
4485         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4486         size_t wantedsize; // how much space was allocated
4487         unsigned char *data; // start of real data (16byte aligned)
4488 }
4489 r_framedata_mem_t;
4490
4491 static r_framedata_mem_t *r_framedata_mem;
4492
4493 void R_FrameData_Reset(void)
4494 {
4495         while (r_framedata_mem)
4496         {
4497                 r_framedata_mem_t *next = r_framedata_mem->purge;
4498                 Mem_Free(r_framedata_mem);
4499                 r_framedata_mem = next;
4500         }
4501 }
4502
4503 static void R_FrameData_Resize(void)
4504 {
4505         size_t wantedsize;
4506         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4507         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4508         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4509         {
4510                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4511                 newmem->wantedsize = wantedsize;
4512                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4513                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4514                 newmem->current = 0;
4515                 newmem->mark = 0;
4516                 newmem->purge = r_framedata_mem;
4517                 r_framedata_mem = newmem;
4518         }
4519 }
4520
4521 void R_FrameData_NewFrame(void)
4522 {
4523         R_FrameData_Resize();
4524         if (!r_framedata_mem)
4525                 return;
4526         // if we ran out of space on the last frame, free the old memory now
4527         while (r_framedata_mem->purge)
4528         {
4529                 // repeatedly remove the second item in the list, leaving only head
4530                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4531                 Mem_Free(r_framedata_mem->purge);
4532                 r_framedata_mem->purge = next;
4533         }
4534         // reset the current mem pointer
4535         r_framedata_mem->current = 0;
4536         r_framedata_mem->mark = 0;
4537 }
4538
4539 void *R_FrameData_Alloc(size_t size)
4540 {
4541         void *data;
4542
4543         // align to 16 byte boundary - the data pointer is already aligned, so we
4544         // only need to ensure the size of every allocation is also aligned
4545         size = (size + 15) & ~15;
4546
4547         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4548         {
4549                 // emergency - we ran out of space, allocate more memory
4550                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4551                 R_FrameData_Resize();
4552         }
4553
4554         data = r_framedata_mem->data + r_framedata_mem->current;
4555         r_framedata_mem->current += size;
4556
4557         // count the usage for stats
4558         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4559         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4560
4561         return (void *)data;
4562 }
4563
4564 void *R_FrameData_Store(size_t size, void *data)
4565 {
4566         void *d = R_FrameData_Alloc(size);
4567         if (d && data)
4568                 memcpy(d, data, size);
4569         return d;
4570 }
4571
4572 void R_FrameData_SetMark(void)
4573 {
4574         if (!r_framedata_mem)
4575                 return;
4576         r_framedata_mem->mark = r_framedata_mem->current;
4577 }
4578
4579 void R_FrameData_ReturnToMark(void)
4580 {
4581         if (!r_framedata_mem)
4582                 return;
4583         r_framedata_mem->current = r_framedata_mem->mark;
4584 }
4585
4586 //==================================================================================
4587
4588 // LordHavoc: animcache originally written by Echon, rewritten since then
4589
4590 /**
4591  * Animation cache prevents re-generating mesh data for an animated model
4592  * multiple times in one frame for lighting, shadowing, reflections, etc.
4593  */
4594
4595 void R_AnimCache_Free(void)
4596 {
4597 }
4598
4599 void R_AnimCache_ClearCache(void)
4600 {
4601         int i;
4602         entity_render_t *ent;
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605         {
4606                 ent = r_refdef.scene.entities[i];
4607                 ent->animcache_vertex3f = NULL;
4608                 ent->animcache_normal3f = NULL;
4609                 ent->animcache_svector3f = NULL;
4610                 ent->animcache_tvector3f = NULL;
4611                 ent->animcache_vertexmesh = NULL;
4612                 ent->animcache_vertex3fbuffer = NULL;
4613                 ent->animcache_vertexmeshbuffer = NULL;
4614         }
4615 }
4616
4617 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4618 {
4619         int i;
4620
4621         // check if we need the meshbuffers
4622         if (!vid.useinterleavedarrays)
4623                 return;
4624
4625         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4626                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4627         // TODO: upload vertex3f buffer?
4628         if (ent->animcache_vertexmesh)
4629         {
4630                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4631                 for (i = 0;i < numvertices;i++)
4632                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4633                 if (ent->animcache_svector3f)
4634                         for (i = 0;i < numvertices;i++)
4635                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4636                 if (ent->animcache_tvector3f)
4637                         for (i = 0;i < numvertices;i++)
4638                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4639                 if (ent->animcache_normal3f)
4640                         for (i = 0;i < numvertices;i++)
4641                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4642                 // TODO: upload vertexmeshbuffer?
4643         }
4644 }
4645
4646 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4647 {
4648         dp_model_t *model = ent->model;
4649         int numvertices;
4650         // see if it's already cached this frame
4651         if (ent->animcache_vertex3f)
4652         {
4653                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4654                 if (wantnormals || wanttangents)
4655                 {
4656                         if (ent->animcache_normal3f)
4657                                 wantnormals = false;
4658                         if (ent->animcache_svector3f)
4659                                 wanttangents = false;
4660                         if (wantnormals || wanttangents)
4661                         {
4662                                 numvertices = model->surfmesh.num_vertices;
4663                                 if (wantnormals)
4664                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665                                 if (wanttangents)
4666                                 {
4667                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4668                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4669                                 }
4670                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4671                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4672                         }
4673                 }
4674         }
4675         else
4676         {
4677                 // see if this ent is worth caching
4678                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4679                         return false;
4680                 // get some memory for this entity and generate mesh data
4681                 numvertices = model->surfmesh.num_vertices;
4682                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4683                 if (wantnormals)
4684                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4685                 if (wanttangents)
4686                 {
4687                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4688                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4689                 }
4690                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4691                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4692         }
4693         return true;
4694 }
4695
4696 void R_AnimCache_CacheVisibleEntities(void)
4697 {
4698         int i;
4699         qboolean wantnormals = true;
4700         qboolean wanttangents = !r_showsurfaces.integer;
4701
4702         switch(vid.renderpath)
4703         {
4704         case RENDERPATH_GL20:
4705         case RENDERPATH_D3D9:
4706         case RENDERPATH_D3D10:
4707         case RENDERPATH_D3D11:
4708         case RENDERPATH_GLES2:
4709                 break;
4710         case RENDERPATH_GL11:
4711         case RENDERPATH_GL13:
4712         case RENDERPATH_GLES1:
4713                 wanttangents = false;
4714                 break;
4715         case RENDERPATH_SOFT:
4716                 break;
4717         }
4718
4719         if (r_shownormals.integer)
4720                 wanttangents = wantnormals = true;
4721
4722         // TODO: thread this
4723         // NOTE: R_PrepareRTLights() also caches entities
4724
4725         for (i = 0;i < r_refdef.scene.numentities;i++)
4726                 if (r_refdef.viewcache.entityvisible[i])
4727                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4728 }
4729
4730 //==================================================================================
4731
4732 extern cvar_t r_overheadsprites_pushback;
4733
4734 static void R_View_UpdateEntityLighting (void)
4735 {
4736         int i;
4737         entity_render_t *ent;
4738         vec3_t tempdiffusenormal, avg;
4739         vec_t f, fa, fd, fdd;
4740         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4741
4742         for (i = 0;i < r_refdef.scene.numentities;i++)
4743         {
4744                 ent = r_refdef.scene.entities[i];
4745
4746                 // skip unseen models
4747                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4748                         continue;
4749
4750                 // skip bsp models
4751                 if (ent->model && ent->model == cl.worldmodel)
4752                 {
4753                         // TODO: use modellight for r_ambient settings on world?
4754                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4755                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4756                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4757                         continue;
4758                 }
4759                 
4760                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4761                 {
4762                         // aleady updated by CSQC
4763                         // TODO: force modellight on BSP models in this case?
4764                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4765                 }
4766                 else
4767                 {
4768                         // fetch the lighting from the worldmodel data
4769                         VectorClear(ent->modellight_ambient);
4770                         VectorClear(ent->modellight_diffuse);
4771                         VectorClear(tempdiffusenormal);
4772                         if (ent->flags & RENDER_LIGHT)
4773                         {
4774                                 vec3_t org;
4775                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4776
4777                                 // complete lightning for lit sprites
4778                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4779                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4780                                 {
4781                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4782                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4783                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4784                                 }
4785                                 else
4786                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4787
4788                                 if(ent->flags & RENDER_EQUALIZE)
4789                                 {
4790                                         // first fix up ambient lighting...
4791                                         if(r_equalize_entities_minambient.value > 0)
4792                                         {
4793                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4794                                                 if(fd > 0)
4795                                                 {
4796                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4797                                                         if(fa < r_equalize_entities_minambient.value * fd)
4798                                                         {
4799                                                                 // solve:
4800                                                                 //   fa'/fd' = minambient
4801                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4802                                                                 //   ...
4803                                                                 //   fa' = fd' * minambient
4804                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4805                                                                 //   ...
4806                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4807                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4808                                                                 //   ...
4809                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4810                                                                 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
4811                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4812                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4813                                                         }
4814                                                 }
4815                                         }
4816
4817                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4818                                         {
4819                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4820                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4821                                                 f = fa + 0.25 * fd;
4822                                                 if(f > 0)
4823                                                 {
4824                                                         // adjust brightness and saturation to target
4825                                                         avg[0] = avg[1] = avg[2] = fa / f;
4826                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4827                                                         avg[0] = avg[1] = avg[2] = fd / f;
4828                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4829                                                 }
4830                                         }
4831                                 }
4832                         }
4833                         else // highly rare
4834                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4835                 }
4836
4837                 // move the light direction into modelspace coordinates for lighting code
4838                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4839                 if(VectorLength2(ent->modellight_lightdir) == 0)
4840                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4841                 VectorNormalize(ent->modellight_lightdir);
4842         }
4843 }
4844
4845 #define MAX_LINEOFSIGHTTRACES 64
4846
4847 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4848 {
4849         int i;
4850         vec3_t boxmins, boxmaxs;
4851         vec3_t start;
4852         vec3_t end;
4853         dp_model_t *model = r_refdef.scene.worldmodel;
4854
4855         if (!model || !model->brush.TraceLineOfSight)
4856                 return true;
4857
4858         // expand the box a little
4859         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4860         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4861         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4862         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4863         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4864         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4865
4866         // return true if eye is inside enlarged box
4867         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4868                 return true;
4869
4870         // try center
4871         VectorCopy(eye, start);
4872         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4873         if (model->brush.TraceLineOfSight(model, start, end))
4874                 return true;
4875
4876         // try various random positions
4877         for (i = 0;i < numsamples;i++)
4878         {
4879                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4880                 if (model->brush.TraceLineOfSight(model, start, end))
4881                         return true;
4882         }
4883
4884         return false;
4885 }
4886
4887
4888 static void R_View_UpdateEntityVisible (void)
4889 {
4890         int i;
4891         int renderimask;
4892         int samples;
4893         entity_render_t *ent;
4894
4895         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4896                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4897                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4898                 :                                                          RENDER_EXTERIORMODEL;
4899         if (!r_drawviewmodel.integer)
4900                 renderimask |= RENDER_VIEWMODEL;
4901         if (!r_drawexteriormodel.integer)
4902                 renderimask |= RENDER_EXTERIORMODEL;
4903         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4904         {
4905                 // worldmodel can check visibility
4906                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         ent = r_refdef.scene.entities[i];
4910                         if (!(ent->flags & renderimask))
4911                         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)))
4912                         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))
4913                                 r_refdef.viewcache.entityvisible[i] = true;
4914                 }
4915         }
4916         else
4917         {
4918                 // no worldmodel or it can't check visibility
4919                 for (i = 0;i < r_refdef.scene.numentities;i++)
4920                 {
4921                         ent = r_refdef.scene.entities[i];
4922                         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));
4923                 }
4924         }
4925         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4926                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4927         {
4928                 for (i = 0;i < r_refdef.scene.numentities;i++)
4929                 {
4930                         if (!r_refdef.viewcache.entityvisible[i])
4931                                 continue;
4932                         ent = r_refdef.scene.entities[i];
4933                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4934                         {
4935                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4936                                 if (samples < 0)
4937                                         continue; // temp entities do pvs only
4938                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4939                                         ent->last_trace_visibility = realtime;
4940                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4941                                         r_refdef.viewcache.entityvisible[i] = 0;
4942                         }
4943                 }
4944         }
4945 }
4946
4947 /// only used if skyrendermasked, and normally returns false
4948 static int R_DrawBrushModelsSky (void)
4949 {
4950         int i, sky;
4951         entity_render_t *ent;
4952
4953         sky = false;
4954         for (i = 0;i < r_refdef.scene.numentities;i++)
4955         {
4956                 if (!r_refdef.viewcache.entityvisible[i])
4957                         continue;
4958                 ent = r_refdef.scene.entities[i];
4959                 if (!ent->model || !ent->model->DrawSky)
4960                         continue;
4961                 ent->model->DrawSky(ent);
4962                 sky = true;
4963         }
4964         return sky;
4965 }
4966
4967 static void R_DrawNoModel(entity_render_t *ent);
4968 static void R_DrawModels(void)
4969 {
4970         int i;
4971         entity_render_t *ent;
4972
4973         for (i = 0;i < r_refdef.scene.numentities;i++)
4974         {
4975                 if (!r_refdef.viewcache.entityvisible[i])
4976                         continue;
4977                 ent = r_refdef.scene.entities[i];
4978                 r_refdef.stats.entities++;
4979                 /*
4980                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4981                 {
4982                         vec3_t f, l, u, o;
4983                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4984                         Con_Printf("R_DrawModels\n");
4985                         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]);
4986                         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);
4987                         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);
4988                 }
4989                 */
4990                 if (ent->model && ent->model->Draw != NULL)
4991                         ent->model->Draw(ent);
4992                 else
4993                         R_DrawNoModel(ent);
4994         }
4995 }
4996
4997 static void R_DrawModelsDepth(void)
4998 {
4999         int i;
5000         entity_render_t *ent;
5001
5002         for (i = 0;i < r_refdef.scene.numentities;i++)
5003         {
5004                 if (!r_refdef.viewcache.entityvisible[i])
5005                         continue;
5006                 ent = r_refdef.scene.entities[i];
5007                 if (ent->model && ent->model->DrawDepth != NULL)
5008                         ent->model->DrawDepth(ent);
5009         }
5010 }
5011
5012 static void R_DrawModelsDebug(void)
5013 {
5014         int i;
5015         entity_render_t *ent;
5016
5017         for (i = 0;i < r_refdef.scene.numentities;i++)
5018         {
5019                 if (!r_refdef.viewcache.entityvisible[i])
5020                         continue;
5021                 ent = r_refdef.scene.entities[i];
5022                 if (ent->model && ent->model->DrawDebug != NULL)
5023                         ent->model->DrawDebug(ent);
5024         }
5025 }
5026
5027 static void R_DrawModelsAddWaterPlanes(void)
5028 {
5029         int i;
5030         entity_render_t *ent;
5031
5032         for (i = 0;i < r_refdef.scene.numentities;i++)
5033         {
5034                 if (!r_refdef.viewcache.entityvisible[i])
5035                         continue;
5036                 ent = r_refdef.scene.entities[i];
5037                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5038                         ent->model->DrawAddWaterPlanes(ent);
5039         }
5040 }
5041
5042 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}};
5043
5044 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5045 {
5046         if (r_hdr_irisadaptation.integer)
5047         {
5048                 vec3_t p;
5049                 vec3_t ambient;
5050                 vec3_t diffuse;
5051                 vec3_t diffusenormal;
5052                 vec3_t forward;
5053                 vec_t brightness = 0.0f;
5054                 vec_t goal;
5055                 vec_t current;
5056                 vec_t d;
5057                 int c;
5058                 VectorCopy(r_refdef.view.forward, forward);
5059                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5060                 {
5061                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5062                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5063                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5064                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5065                         d = DotProduct(forward, diffusenormal);
5066                         brightness += VectorLength(ambient);
5067                         if (d > 0)
5068                                 brightness += d * VectorLength(diffuse);
5069                 }
5070                 brightness *= 1.0f / c;
5071                 brightness += 0.00001f; // make sure it's never zero
5072                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5073                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5074                 current = r_hdr_irisadaptation_value.value;
5075                 if (current < goal)
5076                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5077                 else if (current > goal)
5078                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5079                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5080                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5081         }
5082         else if (r_hdr_irisadaptation_value.value != 1.0f)
5083                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5084 }
5085
5086 static void R_View_SetFrustum(const int *scissor)
5087 {
5088         int i;
5089         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5090         vec3_t forward, left, up, origin, v;
5091
5092         if(scissor)
5093         {
5094                 // flipped x coordinates (because x points left here)
5095                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5096                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5097
5098                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5099                 switch(vid.renderpath)
5100                 {
5101                         case RENDERPATH_D3D9:
5102                         case RENDERPATH_D3D10:
5103                         case RENDERPATH_D3D11:
5104                                 // non-flipped y coordinates
5105                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5106                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5107                                 break;
5108                         case RENDERPATH_SOFT:
5109                         case RENDERPATH_GL11:
5110                         case RENDERPATH_GL13:
5111                         case RENDERPATH_GL20:
5112                         case RENDERPATH_GLES1:
5113                         case RENDERPATH_GLES2:
5114                                 // non-flipped y coordinates
5115                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5117                                 break;
5118                 }
5119         }
5120
5121         // we can't trust r_refdef.view.forward and friends in reflected scenes
5122         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5123
5124 #if 0
5125         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5126         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5127         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5128         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5129         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5130         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5131         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5132         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5133         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5134         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5135         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5136         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5137 #endif
5138
5139 #if 0
5140         zNear = r_refdef.nearclip;
5141         nudge = 1.0 - 1.0 / (1<<23);
5142         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5143         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5144         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5145         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5146         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5147         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5148         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5149         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5150 #endif
5151
5152
5153
5154 #if 0
5155         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5156         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5157         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5158         r_refdef.view.frustum[0].dist = m[15] - m[12];
5159
5160         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5161         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5162         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5163         r_refdef.view.frustum[1].dist = m[15] + m[12];
5164
5165         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5166         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5167         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5168         r_refdef.view.frustum[2].dist = m[15] - m[13];
5169
5170         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5171         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5172         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5173         r_refdef.view.frustum[3].dist = m[15] + m[13];
5174
5175         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5176         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5177         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5178         r_refdef.view.frustum[4].dist = m[15] - m[14];
5179
5180         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5181         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5182         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5183         r_refdef.view.frustum[5].dist = m[15] + m[14];
5184 #endif
5185
5186         if (r_refdef.view.useperspective)
5187         {
5188                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5189                 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]);
5190                 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]);
5191                 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]);
5192                 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]);
5193
5194                 // then the normals from the corners relative to origin
5195                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5196                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5197                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5198                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5199
5200                 // in a NORMAL view, forward cross left == up
5201                 // in a REFLECTED view, forward cross left == down
5202                 // so our cross products above need to be adjusted for a left handed coordinate system
5203                 CrossProduct(forward, left, v);
5204                 if(DotProduct(v, up) < 0)
5205                 {
5206                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5207                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5208                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5209                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5210                 }
5211
5212                 // Leaving those out was a mistake, those were in the old code, and they
5213                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5214                 // I couldn't reproduce it after adding those normalizations. --blub
5215                 VectorNormalize(r_refdef.view.frustum[0].normal);
5216                 VectorNormalize(r_refdef.view.frustum[1].normal);
5217                 VectorNormalize(r_refdef.view.frustum[2].normal);
5218                 VectorNormalize(r_refdef.view.frustum[3].normal);
5219
5220                 // make the corners absolute
5221                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5222                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5223                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5224                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5225
5226                 // one more normal
5227                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5228
5229                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5230                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5231                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5232                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5233                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5234         }
5235         else
5236         {
5237                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5238                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5239                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5240                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5241                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5242                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5243                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5244                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5245                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5246                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5247         }
5248         r_refdef.view.numfrustumplanes = 5;
5249
5250         if (r_refdef.view.useclipplane)
5251         {
5252                 r_refdef.view.numfrustumplanes = 6;
5253                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5254         }
5255
5256         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5257                 PlaneClassify(r_refdef.view.frustum + i);
5258
5259         // LordHavoc: note to all quake engine coders, Quake had a special case
5260         // for 90 degrees which assumed a square view (wrong), so I removed it,
5261         // Quake2 has it disabled as well.
5262
5263         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5264         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5265         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5266         //PlaneClassify(&frustum[0]);
5267
5268         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5269         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5270         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5271         //PlaneClassify(&frustum[1]);
5272
5273         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5274         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5275         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5276         //PlaneClassify(&frustum[2]);
5277
5278         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5279         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5280         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5281         //PlaneClassify(&frustum[3]);
5282
5283         // nearclip plane
5284         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5285         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5286         //PlaneClassify(&frustum[4]);
5287 }
5288
5289 static void R_View_UpdateWithScissor(const int *myscissor)
5290 {
5291         R_Main_ResizeViewCache();
5292         R_View_SetFrustum(myscissor);
5293         R_View_WorldVisibility(r_refdef.view.useclipplane);
5294         R_View_UpdateEntityVisible();
5295         R_View_UpdateEntityLighting();
5296         R_AnimCache_CacheVisibleEntities();
5297 }
5298
5299 static void R_View_Update(void)
5300 {
5301         R_Main_ResizeViewCache();
5302         R_View_SetFrustum(NULL);
5303         R_View_WorldVisibility(r_refdef.view.useclipplane);
5304         R_View_UpdateEntityVisible();
5305         R_View_UpdateEntityLighting();
5306         R_AnimCache_CacheVisibleEntities();
5307 }
5308
5309 float viewscalefpsadjusted = 1.0f;
5310
5311 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5312 {
5313         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5314         scale = bound(0.03125f, scale, 1.0f);
5315         *outwidth = (int)ceil(width * scale);
5316         *outheight = (int)ceil(height * scale);
5317 }
5318
5319 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5320 {
5321         const float *customclipplane = NULL;
5322         float plane[4];
5323         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5324         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5325         {
5326                 // LordHavoc: couldn't figure out how to make this approach the
5327                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5328                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5329                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5330                         dist = r_refdef.view.clipplane.dist;
5331                 plane[0] = r_refdef.view.clipplane.normal[0];
5332                 plane[1] = r_refdef.view.clipplane.normal[1];
5333                 plane[2] = r_refdef.view.clipplane.normal[2];
5334                 plane[3] = -dist;
5335                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5336         }
5337
5338         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5339         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5340
5341         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5342         if (!r_refdef.view.useperspective)
5343                 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);
5344         else if (vid.stencil && r_useinfinitefarclip.integer)
5345                 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);
5346         else
5347                 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);
5348         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5349         R_SetViewport(&r_refdef.view.viewport);
5350         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5351         {
5352                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5353                 float screenplane[4];
5354                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5355                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5356                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5357                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5358                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5359         }
5360 }
5361
5362 void R_EntityMatrix(const matrix4x4_t *matrix)
5363 {
5364         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5365         {
5366                 gl_modelmatrixchanged = false;
5367                 gl_modelmatrix = *matrix;
5368                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5369                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5370                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5371                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5372                 CHECKGLERROR
5373                 switch(vid.renderpath)
5374                 {
5375                 case RENDERPATH_D3D9:
5376 #ifdef SUPPORTD3D
5377                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5378                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5379 #endif
5380                         break;
5381                 case RENDERPATH_D3D10:
5382                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5383                         break;
5384                 case RENDERPATH_D3D11:
5385                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5386                         break;
5387                 case RENDERPATH_GL11:
5388                 case RENDERPATH_GL13:
5389                 case RENDERPATH_GLES1:
5390                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5391                         break;
5392                 case RENDERPATH_SOFT:
5393                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5394                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5395                         break;
5396                 case RENDERPATH_GL20:
5397                 case RENDERPATH_GLES2:
5398                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5399                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5400                         break;
5401                 }
5402         }
5403 }
5404
5405 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5406 {
5407         r_viewport_t viewport;
5408
5409         CHECKGLERROR
5410
5411         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5412         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);
5413         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5414         R_SetViewport(&viewport);
5415         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5416         GL_Color(1, 1, 1, 1);
5417         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5418         GL_BlendFunc(GL_ONE, GL_ZERO);
5419         GL_ScissorTest(false);
5420         GL_DepthMask(false);
5421         GL_DepthRange(0, 1);
5422         GL_DepthTest(false);
5423         GL_DepthFunc(GL_LEQUAL);
5424         R_EntityMatrix(&identitymatrix);
5425         R_Mesh_ResetTextureState();
5426         GL_PolygonOffset(0, 0);
5427         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5428         switch(vid.renderpath)
5429         {
5430         case RENDERPATH_GL11:
5431         case RENDERPATH_GL13:
5432         case RENDERPATH_GL20:
5433         case RENDERPATH_GLES1:
5434         case RENDERPATH_GLES2:
5435                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5436                 break;
5437         case RENDERPATH_D3D9:
5438         case RENDERPATH_D3D10:
5439         case RENDERPATH_D3D11:
5440         case RENDERPATH_SOFT:
5441                 break;
5442         }
5443         GL_CullFace(GL_NONE);
5444
5445         CHECKGLERROR
5446 }
5447
5448 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5449 {
5450         DrawQ_Finish();
5451
5452         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5453 }
5454
5455 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5456 {
5457         DrawQ_Finish();
5458
5459         R_SetupView(true, fbo, depthtexture, colortexture);
5460         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5461         GL_Color(1, 1, 1, 1);
5462         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5463         GL_BlendFunc(GL_ONE, GL_ZERO);
5464         GL_ScissorTest(true);
5465         GL_DepthMask(true);
5466         GL_DepthRange(0, 1);
5467         GL_DepthTest(true);
5468         GL_DepthFunc(GL_LEQUAL);
5469         R_EntityMatrix(&identitymatrix);
5470         R_Mesh_ResetTextureState();
5471         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5472         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5473         switch(vid.renderpath)
5474         {
5475         case RENDERPATH_GL11:
5476         case RENDERPATH_GL13:
5477         case RENDERPATH_GL20:
5478         case RENDERPATH_GLES1:
5479         case RENDERPATH_GLES2:
5480                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5481                 break;
5482         case RENDERPATH_D3D9:
5483         case RENDERPATH_D3D10:
5484         case RENDERPATH_D3D11:
5485         case RENDERPATH_SOFT:
5486                 break;
5487         }
5488         GL_CullFace(r_refdef.view.cullface_back);
5489 }
5490
5491 /*
5492 ================
5493 R_RenderView_UpdateViewVectors
5494 ================
5495 */
5496 void R_RenderView_UpdateViewVectors(void)
5497 {
5498         // break apart the view matrix into vectors for various purposes
5499         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5500         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5501         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5502         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5503         // make an inverted copy of the view matrix for tracking sprites
5504         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5505 }
5506
5507 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5508 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5509
5510 static void R_Water_StartFrame(void)
5511 {
5512         int i;
5513         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5514         r_waterstate_waterplane_t *p;
5515         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5516
5517         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5518                 return;
5519
5520         switch(vid.renderpath)
5521         {
5522         case RENDERPATH_GL20:
5523         case RENDERPATH_D3D9:
5524         case RENDERPATH_D3D10:
5525         case RENDERPATH_D3D11:
5526         case RENDERPATH_SOFT:
5527         case RENDERPATH_GLES2:
5528                 break;
5529         case RENDERPATH_GL11:
5530         case RENDERPATH_GL13:
5531         case RENDERPATH_GLES1:
5532                 return;
5533         }
5534
5535         // set waterwidth and waterheight to the water resolution that will be
5536         // used (often less than the screen resolution for faster rendering)
5537         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5538
5539         // calculate desired texture sizes
5540         // can't use water if the card does not support the texture size
5541         if (!r_water.integer || r_showsurfaces.integer)
5542                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5543         else if (vid.support.arb_texture_non_power_of_two)
5544         {
5545                 texturewidth = waterwidth;
5546                 textureheight = waterheight;
5547                 camerawidth = waterwidth;
5548                 cameraheight = waterheight;
5549         }
5550         else
5551         {
5552                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5553                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5554                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5555                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5556         }
5557
5558         // allocate textures as needed
5559         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))
5560         {
5561                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5562                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5563                 {
5564                         if (p->texture_refraction)
5565                                 R_FreeTexture(p->texture_refraction);
5566                         p->texture_refraction = NULL;
5567                         if (p->fbo_refraction)
5568                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5569                         p->fbo_refraction = 0;
5570                         if (p->texture_reflection)
5571                                 R_FreeTexture(p->texture_reflection);
5572                         p->texture_reflection = NULL;
5573                         if (p->fbo_reflection)
5574                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5575                         p->fbo_reflection = 0;
5576                         if (p->texture_camera)
5577                                 R_FreeTexture(p->texture_camera);
5578                         p->texture_camera = NULL;
5579                         if (p->fbo_camera)
5580                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5581                         p->fbo_camera = 0;
5582                 }
5583                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5584                 r_fb.water.texturewidth = texturewidth;
5585                 r_fb.water.textureheight = textureheight;
5586                 r_fb.water.camerawidth = camerawidth;
5587                 r_fb.water.cameraheight = cameraheight;
5588         }
5589
5590         if (r_fb.water.texturewidth)
5591         {
5592                 int scaledwidth, scaledheight;
5593
5594                 r_fb.water.enabled = true;
5595
5596                 // water resolution is usually reduced
5597                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5598                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5599                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5600
5601                 // set up variables that will be used in shader setup
5602                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5603                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5604                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5605                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5606         }
5607
5608         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5609         r_fb.water.numwaterplanes = 0;
5610 }
5611
5612 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5613 {
5614         int planeindex, bestplaneindex, vertexindex;
5615         vec3_t mins, maxs, normal, center, v, n;
5616         vec_t planescore, bestplanescore;
5617         mplane_t plane;
5618         r_waterstate_waterplane_t *p;
5619         texture_t *t = R_GetCurrentTexture(surface->texture);
5620
5621         rsurface.texture = t;
5622         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5623         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5624         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5625                 return;
5626         // average the vertex normals, find the surface bounds (after deformvertexes)
5627         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5628         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5629         VectorCopy(n, normal);
5630         VectorCopy(v, mins);
5631         VectorCopy(v, maxs);
5632         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5633         {
5634                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5635                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5636                 VectorAdd(normal, n, normal);
5637                 mins[0] = min(mins[0], v[0]);
5638                 mins[1] = min(mins[1], v[1]);
5639                 mins[2] = min(mins[2], v[2]);
5640                 maxs[0] = max(maxs[0], v[0]);
5641                 maxs[1] = max(maxs[1], v[1]);
5642                 maxs[2] = max(maxs[2], v[2]);
5643         }
5644         VectorNormalize(normal);
5645         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5646
5647         VectorCopy(normal, plane.normal);
5648         VectorNormalize(plane.normal);
5649         plane.dist = DotProduct(center, plane.normal);
5650         PlaneClassify(&plane);
5651         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5652         {
5653                 // skip backfaces (except if nocullface is set)
5654 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5655 //                      return;
5656                 VectorNegate(plane.normal, plane.normal);
5657                 plane.dist *= -1;
5658                 PlaneClassify(&plane);
5659         }
5660
5661
5662         // find a matching plane if there is one
5663         bestplaneindex = -1;
5664         bestplanescore = 1048576.0f;
5665         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5666         {
5667                 if(p->camera_entity == t->camera_entity)
5668                 {
5669                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5670                         if (bestplaneindex < 0 || bestplanescore > planescore)
5671                         {
5672                                 bestplaneindex = planeindex;
5673                                 bestplanescore = planescore;
5674                         }
5675                 }
5676         }
5677         planeindex = bestplaneindex;
5678         p = r_fb.water.waterplanes + planeindex;
5679
5680         // if this surface does not fit any known plane rendered this frame, add one
5681         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5682         {
5683                 // store the new plane
5684                 planeindex = r_fb.water.numwaterplanes++;
5685                 p = r_fb.water.waterplanes + planeindex;
5686                 p->plane = plane;
5687                 // clear materialflags and pvs
5688                 p->materialflags = 0;
5689                 p->pvsvalid = false;
5690                 p->camera_entity = t->camera_entity;
5691                 VectorCopy(mins, p->mins);
5692                 VectorCopy(maxs, p->maxs);
5693         }
5694         else
5695         {
5696                 // merge mins/maxs when we're adding this surface to the plane
5697                 p->mins[0] = min(p->mins[0], mins[0]);
5698                 p->mins[1] = min(p->mins[1], mins[1]);
5699                 p->mins[2] = min(p->mins[2], mins[2]);
5700                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5701                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5702                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5703         }
5704         // merge this surface's materialflags into the waterplane
5705         p->materialflags |= t->currentmaterialflags;
5706         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5707         {
5708                 // merge this surface's PVS into the waterplane
5709                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5710                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5711                 {
5712                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5713                         p->pvsvalid = true;
5714                 }
5715         }
5716 }
5717
5718 extern cvar_t r_drawparticles;
5719 extern cvar_t r_drawdecals;
5720
5721 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5722 {
5723         int myscissor[4];
5724         r_refdef_view_t originalview;
5725         r_refdef_view_t myview;
5726         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;
5727         r_waterstate_waterplane_t *p;
5728         vec3_t visorigin;
5729         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5730         char vabuf[1024];
5731
5732         originalview = r_refdef.view;
5733
5734         // lowquality hack, temporarily shut down some cvars and restore afterwards
5735         qualityreduction = r_water_lowquality.integer;
5736         if (qualityreduction > 0)
5737         {
5738                 if (qualityreduction >= 1)
5739                 {
5740                         old_r_shadows = r_shadows.integer;
5741                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5742                         old_r_dlight = r_shadow_realtime_dlight.integer;
5743                         Cvar_SetValueQuick(&r_shadows, 0);
5744                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5745                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5746                 }
5747                 if (qualityreduction >= 2)
5748                 {
5749                         old_r_dynamic = r_dynamic.integer;
5750                         old_r_particles = r_drawparticles.integer;
5751                         old_r_decals = r_drawdecals.integer;
5752                         Cvar_SetValueQuick(&r_dynamic, 0);
5753                         Cvar_SetValueQuick(&r_drawparticles, 0);
5754                         Cvar_SetValueQuick(&r_drawdecals, 0);
5755                 }
5756         }
5757
5758         // make sure enough textures are allocated
5759         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5760         {
5761                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5762                 {
5763                         if (!p->texture_refraction)
5764                                 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);
5765                         if (!p->texture_refraction)
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_refraction == 0)
5772                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5773                         }
5774                 }
5775                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5776                 {
5777                         if (!p->texture_camera)
5778                                 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);
5779                         if (!p->texture_camera)
5780                                 goto error;
5781                         if (usewaterfbo)
5782                         {
5783                                 if (r_fb.water.depthtexture == NULL)
5784                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5785                                 if (p->fbo_camera == 0)
5786                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5787                         }
5788                 }
5789
5790                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5791                 {
5792                         if (!p->texture_reflection)
5793                                 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);
5794                         if (!p->texture_reflection)
5795                                 goto error;
5796                         if (usewaterfbo)
5797                         {
5798                                 if (r_fb.water.depthtexture == NULL)
5799                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5800                                 if (p->fbo_reflection == 0)
5801                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5802                         }
5803                 }
5804         }
5805
5806         // render views
5807         r_refdef.view = originalview;
5808         r_refdef.view.showdebug = false;
5809         r_refdef.view.width = r_fb.water.waterwidth;
5810         r_refdef.view.height = r_fb.water.waterheight;
5811         r_refdef.view.useclipplane = true;
5812         myview = r_refdef.view;
5813         r_fb.water.renderingscene = true;
5814         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5815         {
5816                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5817                 {
5818                         r_refdef.view = myview;
5819                         if(r_water_scissormode.integer)
5820                         {
5821                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5822                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5823                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5824                         }
5825
5826                         // render reflected scene and copy into texture
5827                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5828                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5829                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5830                         r_refdef.view.clipplane = p->plane;
5831                         // reverse the cullface settings for this render
5832                         r_refdef.view.cullface_front = GL_FRONT;
5833                         r_refdef.view.cullface_back = GL_BACK;
5834                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5835                         {
5836                                 r_refdef.view.usecustompvs = true;
5837                                 if (p->pvsvalid)
5838                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5839                                 else
5840                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5841                         }
5842
5843                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5844                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5845                         R_ClearScreen(r_refdef.fogenabled);
5846                         if(r_water_scissormode.integer & 2)
5847                                 R_View_UpdateWithScissor(myscissor);
5848                         else
5849                                 R_View_Update();
5850                         if(r_water_scissormode.integer & 1)
5851                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5852                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5853
5854                         if (!p->fbo_reflection)
5855                                 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);
5856                         r_fb.water.hideplayer = false;
5857                 }
5858
5859                 // render the normal view scene and copy into texture
5860                 // (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)
5861                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5862                 {
5863                         r_refdef.view = myview;
5864                         if(r_water_scissormode.integer)
5865                         {
5866                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5867                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5868                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5869                         }
5870
5871                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5872
5873                         r_refdef.view.clipplane = p->plane;
5874                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5875                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5876
5877                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5878                         {
5879                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5880                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5881                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5882                                 R_RenderView_UpdateViewVectors();
5883                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5884                                 {
5885                                         r_refdef.view.usecustompvs = true;
5886                                         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);
5887                                 }
5888                         }
5889
5890                         PlaneClassify(&r_refdef.view.clipplane);
5891
5892                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5893                         R_ClearScreen(r_refdef.fogenabled);
5894                         if(r_water_scissormode.integer & 2)
5895                                 R_View_UpdateWithScissor(myscissor);
5896                         else
5897                                 R_View_Update();
5898                         if(r_water_scissormode.integer & 1)
5899                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5900                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5901
5902                         if (!p->fbo_refraction)
5903                                 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);
5904                         r_fb.water.hideplayer = false;
5905                 }
5906                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5907                 {
5908                         r_refdef.view = myview;
5909
5910                         r_refdef.view.clipplane = p->plane;
5911                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5912                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5913
5914                         r_refdef.view.width = r_fb.water.camerawidth;
5915                         r_refdef.view.height = r_fb.water.cameraheight;
5916                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5917                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5918                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5919                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5920
5921                         if(p->camera_entity)
5922                         {
5923                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5924                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5925                         }
5926
5927                         // note: all of the view is used for displaying... so
5928                         // there is no use in scissoring
5929
5930                         // reverse the cullface settings for this render
5931                         r_refdef.view.cullface_front = GL_FRONT;
5932                         r_refdef.view.cullface_back = GL_BACK;
5933                         // also reverse the view matrix
5934                         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
5935                         R_RenderView_UpdateViewVectors();
5936                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5937                         {
5938                                 r_refdef.view.usecustompvs = true;
5939                                 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);
5940                         }
5941                         
5942                         // camera needs no clipplane
5943                         r_refdef.view.useclipplane = false;
5944
5945                         PlaneClassify(&r_refdef.view.clipplane);
5946
5947                         r_fb.water.hideplayer = false;
5948
5949                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5950                         R_ClearScreen(r_refdef.fogenabled);
5951                         R_View_Update();
5952                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5953
5954                         if (!p->fbo_camera)
5955                                 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);
5956                         r_fb.water.hideplayer = false;
5957                 }
5958
5959         }
5960         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5961         r_fb.water.renderingscene = false;
5962         r_refdef.view = originalview;
5963         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5964         if (!r_fb.water.depthtexture)
5965                 R_ClearScreen(r_refdef.fogenabled);
5966         R_View_Update();
5967         goto finish;
5968 error:
5969         r_refdef.view = originalview;
5970         r_fb.water.renderingscene = false;
5971         Cvar_SetValueQuick(&r_water, 0);
5972         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5973 finish:
5974         // lowquality hack, restore cvars
5975         if (qualityreduction > 0)
5976         {
5977                 if (qualityreduction >= 1)
5978                 {
5979                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5980                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5981                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5982                 }
5983                 if (qualityreduction >= 2)
5984                 {
5985                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5986                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5987                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5988                 }
5989         }
5990 }
5991
5992 static void R_Bloom_StartFrame(void)
5993 {
5994         int i;
5995         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5996         int viewwidth, viewheight;
5997         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5998         textype_t textype = TEXTYPE_COLORBUFFER;
5999
6000         switch (vid.renderpath)
6001         {
6002         case RENDERPATH_GL20:
6003                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6004                 if (vid.support.ext_framebuffer_object)
6005                 {
6006                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6007                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6008                 }
6009                 break;
6010         case RENDERPATH_GL11:
6011         case RENDERPATH_GL13:
6012         case RENDERPATH_GLES1:
6013         case RENDERPATH_GLES2:
6014         case RENDERPATH_D3D9:
6015         case RENDERPATH_D3D10:
6016         case RENDERPATH_D3D11:
6017                 r_fb.usedepthtextures = false;
6018                 break;
6019         case RENDERPATH_SOFT:
6020                 r_fb.usedepthtextures = true;
6021                 break;
6022         }
6023
6024         if (r_viewscale_fpsscaling.integer)
6025         {
6026                 double actualframetime;
6027                 double targetframetime;
6028                 double adjust;
6029                 actualframetime = r_refdef.lastdrawscreentime;
6030                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6031                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6032                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6033                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6034                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6035                 viewscalefpsadjusted += adjust;
6036                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6037         }
6038         else
6039                 viewscalefpsadjusted = 1.0f;
6040
6041         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6042
6043         switch(vid.renderpath)
6044         {
6045         case RENDERPATH_GL20:
6046         case RENDERPATH_D3D9:
6047         case RENDERPATH_D3D10:
6048         case RENDERPATH_D3D11:
6049         case RENDERPATH_SOFT:
6050         case RENDERPATH_GLES2:
6051                 break;
6052         case RENDERPATH_GL11:
6053         case RENDERPATH_GL13:
6054         case RENDERPATH_GLES1:
6055                 return;
6056         }
6057
6058         // set bloomwidth and bloomheight to the bloom resolution that will be
6059         // used (often less than the screen resolution for faster rendering)
6060         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6061         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6062         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6063         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6064         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6065
6066         // calculate desired texture sizes
6067         if (vid.support.arb_texture_non_power_of_two)
6068         {
6069                 screentexturewidth = vid.width;
6070                 screentextureheight = vid.height;
6071                 bloomtexturewidth = r_fb.bloomwidth;
6072                 bloomtextureheight = r_fb.bloomheight;
6073         }
6074         else
6075         {
6076                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6077                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6078                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6079                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6080         }
6081
6082         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))
6083         {
6084                 Cvar_SetValueQuick(&r_bloom, 0);
6085                 Cvar_SetValueQuick(&r_motionblur, 0);
6086                 Cvar_SetValueQuick(&r_damageblur, 0);
6087         }
6088
6089         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6090          && !r_bloom.integer
6091          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6092          && !useviewfbo
6093          && r_viewscale.value == 1.0f
6094          && !r_viewscale_fpsscaling.integer)
6095                 screentexturewidth = screentextureheight = 0;
6096         if (!r_bloom.integer)
6097                 bloomtexturewidth = bloomtextureheight = 0;
6098
6099         // allocate textures as needed
6100         if (r_fb.screentexturewidth != screentexturewidth
6101          || r_fb.screentextureheight != screentextureheight
6102          || r_fb.bloomtexturewidth != bloomtexturewidth
6103          || r_fb.bloomtextureheight != bloomtextureheight
6104          || r_fb.textype != textype
6105          || useviewfbo != (r_fb.fbo != 0))
6106         {
6107                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6108                 {
6109                         if (r_fb.bloomtexture[i])
6110                                 R_FreeTexture(r_fb.bloomtexture[i]);
6111                         r_fb.bloomtexture[i] = NULL;
6112
6113                         if (r_fb.bloomfbo[i])
6114                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6115                         r_fb.bloomfbo[i] = 0;
6116                 }
6117
6118                 if (r_fb.fbo)
6119                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6120                 r_fb.fbo = 0;
6121
6122                 if (r_fb.colortexture)
6123                         R_FreeTexture(r_fb.colortexture);
6124                 r_fb.colortexture = NULL;
6125
6126                 if (r_fb.depthtexture)
6127                         R_FreeTexture(r_fb.depthtexture);
6128                 r_fb.depthtexture = NULL;
6129
6130                 if (r_fb.ghosttexture)
6131                         R_FreeTexture(r_fb.ghosttexture);
6132                 r_fb.ghosttexture = NULL;
6133
6134                 r_fb.screentexturewidth = screentexturewidth;
6135                 r_fb.screentextureheight = screentextureheight;
6136                 r_fb.bloomtexturewidth = bloomtexturewidth;
6137                 r_fb.bloomtextureheight = bloomtextureheight;
6138                 r_fb.textype = textype;
6139
6140                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6141                 {
6142                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6143                                 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);
6144                         r_fb.ghosttexture_valid = false;
6145                         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);
6146                         if (useviewfbo)
6147                         {
6148                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6149                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6150                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6151                         }
6152                 }
6153
6154                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6155                 {
6156                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6157                         {
6158                                 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);
6159                                 if (useviewfbo)
6160                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6161                         }
6162                 }
6163         }
6164
6165         // bloom texture is a different resolution
6166         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6167         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6168         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6169         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6170         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6171
6172         // set up a texcoord array for the full resolution screen image
6173         // (we have to keep this around to copy back during final render)
6174         r_fb.screentexcoord2f[0] = 0;
6175         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6176         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6177         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6178         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6179         r_fb.screentexcoord2f[5] = 0;
6180         r_fb.screentexcoord2f[6] = 0;
6181         r_fb.screentexcoord2f[7] = 0;
6182
6183         if(r_fb.fbo) 
6184         {
6185                 for (i = 1;i < 8;i += 2)
6186                 {
6187                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6188                 }
6189         }
6190
6191         // set up a texcoord array for the reduced resolution bloom image
6192         // (which will be additive blended over the screen image)
6193         r_fb.bloomtexcoord2f[0] = 0;
6194         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6195         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6196         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6197         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6198         r_fb.bloomtexcoord2f[5] = 0;
6199         r_fb.bloomtexcoord2f[6] = 0;
6200         r_fb.bloomtexcoord2f[7] = 0;
6201
6202         switch(vid.renderpath)
6203         {
6204         case RENDERPATH_GL11:
6205         case RENDERPATH_GL13:
6206         case RENDERPATH_GL20:
6207         case RENDERPATH_SOFT:
6208         case RENDERPATH_GLES1:
6209         case RENDERPATH_GLES2:
6210                 break;
6211         case RENDERPATH_D3D9:
6212         case RENDERPATH_D3D10:
6213         case RENDERPATH_D3D11:
6214                 for (i = 0;i < 4;i++)
6215                 {
6216                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6217                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6218                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6219                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6220                 }
6221                 break;
6222         }
6223
6224         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6225
6226         if (r_fb.fbo)
6227                 r_refdef.view.clear = true;
6228 }
6229
6230 static void R_Bloom_MakeTexture(void)
6231 {
6232         int x, range, dir;
6233         float xoffset, yoffset, r, brighten;
6234         rtexture_t *intex;
6235         float colorscale = r_bloom_colorscale.value;
6236
6237         r_refdef.stats.bloom++;
6238     
6239 #if 0
6240     // this copy is unnecessary since it happens in R_BlendView already
6241         if (!r_fb.fbo)
6242         {
6243                 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);
6244                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6245         }
6246 #endif
6247
6248         // scale down screen texture to the bloom texture size
6249         CHECKGLERROR
6250         r_fb.bloomindex = 0;
6251         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6252         R_SetViewport(&r_fb.bloomviewport);
6253         GL_DepthTest(false);
6254         GL_BlendFunc(GL_ONE, GL_ZERO);
6255         GL_Color(colorscale, colorscale, colorscale, 1);
6256         // 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...
6257         switch(vid.renderpath)
6258         {
6259         case RENDERPATH_GL11:
6260         case RENDERPATH_GL13:
6261         case RENDERPATH_GL20:
6262         case RENDERPATH_GLES1:
6263         case RENDERPATH_GLES2:
6264         case RENDERPATH_SOFT:
6265                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6266                 break;
6267         case RENDERPATH_D3D9:
6268         case RENDERPATH_D3D10:
6269         case RENDERPATH_D3D11:
6270                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6271                 break;
6272         }
6273         // TODO: do boxfilter scale-down in shader?
6274         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6275         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6276         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6277
6278         // we now have a properly scaled bloom image
6279         if (!r_fb.bloomfbo[r_fb.bloomindex])
6280         {
6281                 // copy it into the bloom texture
6282                 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);
6283                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6284         }
6285
6286         // multiply bloom image by itself as many times as desired
6287         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6288         {
6289                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6290                 r_fb.bloomindex ^= 1;
6291                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6292                 x *= 2;
6293                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6294                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6295                 {
6296                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6297                         GL_Color(r,r,r,1); // apply fix factor
6298                 }
6299                 else
6300                 {
6301                         if(x <= 2)
6302                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6303                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6304                         GL_Color(1,1,1,1); // no fix factor supported here
6305                 }
6306                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6307                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6308                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6309                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6310
6311                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6312                 {
6313                         // copy the darkened image to a texture
6314                         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);
6315                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6316                 }
6317         }
6318
6319         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6320         brighten = r_bloom_brighten.value;
6321         brighten = sqrt(brighten);
6322         if(range >= 1)
6323                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6324
6325         for (dir = 0;dir < 2;dir++)
6326         {
6327                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6328                 r_fb.bloomindex ^= 1;
6329                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6330                 // blend on at multiple vertical offsets to achieve a vertical blur
6331                 // TODO: do offset blends using GLSL
6332                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6333                 GL_BlendFunc(GL_ONE, GL_ZERO);
6334                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6335                 for (x = -range;x <= range;x++)
6336                 {
6337                         if (!dir){xoffset = 0;yoffset = x;}
6338                         else {xoffset = x;yoffset = 0;}
6339                         xoffset /= (float)r_fb.bloomtexturewidth;
6340                         yoffset /= (float)r_fb.bloomtextureheight;
6341                         // compute a texcoord array with the specified x and y offset
6342                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6343                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6344                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6345                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6346                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6347                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6348                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6349                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6350                         // this r value looks like a 'dot' particle, fading sharply to
6351                         // black at the edges
6352                         // (probably not realistic but looks good enough)
6353                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6354                         //r = brighten/(range*2+1);
6355                         r = brighten / (range * 2 + 1);
6356                         if(range >= 1)
6357                                 r *= (1 - x*x/(float)(range*range));
6358                         GL_Color(r, r, r, 1);
6359                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6360                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6361                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6362                         GL_BlendFunc(GL_ONE, GL_ONE);
6363                 }
6364
6365                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6366                 {
6367                         // copy the vertically or horizontally blurred bloom view to a texture
6368                         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);
6369                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6370                 }
6371         }
6372 }
6373
6374 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6375 {
6376         unsigned int permutation;
6377         float uservecs[4][4];
6378
6379         switch (vid.renderpath)
6380         {
6381         case RENDERPATH_GL20:
6382         case RENDERPATH_D3D9:
6383         case RENDERPATH_D3D10:
6384         case RENDERPATH_D3D11:
6385         case RENDERPATH_SOFT:
6386         case RENDERPATH_GLES2:
6387                 permutation =
6388                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6389                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6390                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6391                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6392                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6393
6394                 if (r_fb.colortexture)
6395                 {
6396                         if (!r_fb.fbo)
6397                         {
6398                                 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);
6399                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6400                         }
6401
6402                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6403                         {
6404                                 // declare variables
6405                                 float blur_factor, blur_mouseaccel, blur_velocity;
6406                                 static float blur_average; 
6407                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6408
6409                                 // set a goal for the factoring
6410                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6411                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6412                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6413                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6414                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6415                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6416
6417                                 // from the goal, pick an averaged value between goal and last value
6418                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6419                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6420
6421                                 // enforce minimum amount of blur 
6422                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6423
6424                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6425
6426                                 // calculate values into a standard alpha
6427                                 cl.motionbluralpha = 1 - exp(-
6428                                                 (
6429                                                  (r_motionblur.value * blur_factor / 80)
6430                                                  +
6431                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6432                                                 )
6433                                                 /
6434                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6435                                           );
6436
6437                                 // randomization for the blur value to combat persistent ghosting
6438                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6439                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6440
6441                                 // apply the blur
6442                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6443                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6444                                 {
6445                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6446                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6447                                         switch(vid.renderpath)
6448                                         {
6449                                         case RENDERPATH_GL11:
6450                                         case RENDERPATH_GL13:
6451                                         case RENDERPATH_GL20:
6452                                         case RENDERPATH_GLES1:
6453                                         case RENDERPATH_GLES2:
6454                                         case RENDERPATH_SOFT:
6455                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6456                                                 break;
6457                                         case RENDERPATH_D3D9:
6458                                         case RENDERPATH_D3D10:
6459                                         case RENDERPATH_D3D11:
6460                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6461                                                 break;
6462                                         }
6463                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6464                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6465                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6466                                 }
6467
6468                                 // updates old view angles for next pass
6469                                 VectorCopy(cl.viewangles, blur_oldangles);
6470
6471                                 // copy view into the ghost texture
6472                                 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);
6473                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6474                                 r_fb.ghosttexture_valid = true;
6475                         }
6476                 }
6477                 else
6478                 {
6479                         // no r_fb.colortexture means we're rendering to the real fb
6480                         // we may still have to do view tint...
6481                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6482                         {
6483                                 // apply a color tint to the whole view
6484                                 R_ResetViewRendering2D(0, NULL, NULL);
6485                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6486                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6487                                 R_SetupShader_Generic_NoTexture(false, true);
6488                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6489                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6490                         }
6491                         break; // no screen processing, no bloom, skip it
6492                 }
6493
6494                 if (r_fb.bloomtexture[0])
6495                 {
6496                         // make the bloom texture
6497                         R_Bloom_MakeTexture();
6498                 }
6499
6500 #if _MSC_VER >= 1400
6501 #define sscanf sscanf_s
6502 #endif
6503                 memset(uservecs, 0, sizeof(uservecs));
6504                 if (r_glsl_postprocess_uservec1_enable.integer)
6505                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6506                 if (r_glsl_postprocess_uservec2_enable.integer)
6507                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6508                 if (r_glsl_postprocess_uservec3_enable.integer)
6509                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6510                 if (r_glsl_postprocess_uservec4_enable.integer)
6511                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6512
6513                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6514                 GL_Color(1, 1, 1, 1);
6515                 GL_BlendFunc(GL_ONE, GL_ZERO);
6516
6517                 switch(vid.renderpath)
6518                 {
6519                 case RENDERPATH_GL20:
6520                 case RENDERPATH_GLES2:
6521                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6522                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6523                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6524                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6525                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6526                         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]);
6527                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6528                         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]);
6529                         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]);
6530                         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]);
6531                         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]);
6532                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6533                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6534                         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);
6535                         break;
6536                 case RENDERPATH_D3D9:
6537 #ifdef SUPPORTD3D
6538                         // 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...
6539                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6540                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6541                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6542                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6543                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6544                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6545                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6546                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6547                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6548                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6549                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6550                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6551                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6552                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6553 #endif
6554                         break;
6555                 case RENDERPATH_D3D10:
6556                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6557                         break;
6558                 case RENDERPATH_D3D11:
6559                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6560                         break;
6561                 case RENDERPATH_SOFT:
6562                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6563                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6564                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6565                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6566                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6567                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6568                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6569                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6570                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6571                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6572                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6573                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6574                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6576                         break;
6577                 default:
6578                         break;
6579                 }
6580                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6581                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6582                 break;
6583         case RENDERPATH_GL11:
6584         case RENDERPATH_GL13:
6585         case RENDERPATH_GLES1:
6586                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6587                 {
6588                         // apply a color tint to the whole view
6589                         R_ResetViewRendering2D(0, NULL, NULL);
6590                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6591                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6592                         R_SetupShader_Generic_NoTexture(false, true);
6593                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6594                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6595                 }
6596                 break;
6597         }
6598 }
6599
6600 matrix4x4_t r_waterscrollmatrix;
6601
6602 void R_UpdateFog(void)
6603 {
6604         // Nehahra fog
6605         if (gamemode == GAME_NEHAHRA)
6606         {
6607                 if (gl_fogenable.integer)
6608                 {
6609                         r_refdef.oldgl_fogenable = true;
6610                         r_refdef.fog_density = gl_fogdensity.value;
6611                         r_refdef.fog_red = gl_fogred.value;
6612                         r_refdef.fog_green = gl_foggreen.value;
6613                         r_refdef.fog_blue = gl_fogblue.value;
6614                         r_refdef.fog_alpha = 1;
6615                         r_refdef.fog_start = 0;
6616                         r_refdef.fog_end = gl_skyclip.value;
6617                         r_refdef.fog_height = 1<<30;
6618                         r_refdef.fog_fadedepth = 128;
6619                 }
6620                 else if (r_refdef.oldgl_fogenable)
6621                 {
6622                         r_refdef.oldgl_fogenable = false;
6623                         r_refdef.fog_density = 0;
6624                         r_refdef.fog_red = 0;
6625                         r_refdef.fog_green = 0;
6626                         r_refdef.fog_blue = 0;
6627                         r_refdef.fog_alpha = 0;
6628                         r_refdef.fog_start = 0;
6629                         r_refdef.fog_end = 0;
6630                         r_refdef.fog_height = 1<<30;
6631                         r_refdef.fog_fadedepth = 128;
6632                 }
6633         }
6634
6635         // fog parms
6636         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6637         r_refdef.fog_start = max(0, r_refdef.fog_start);
6638         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6639
6640         if (r_refdef.fog_density && r_drawfog.integer)
6641         {
6642                 r_refdef.fogenabled = true;
6643                 // this is the point where the fog reaches 0.9986 alpha, which we
6644                 // consider a good enough cutoff point for the texture
6645                 // (0.9986 * 256 == 255.6)
6646                 if (r_fog_exp2.integer)
6647                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6648                 else
6649                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6650                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6651                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6652                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6653                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6654                         R_BuildFogHeightTexture();
6655                 // fog color was already set
6656                 // update the fog texture
6657                 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)
6658                         R_BuildFogTexture();
6659                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6660                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6661         }
6662         else
6663                 r_refdef.fogenabled = false;
6664
6665         // fog color
6666         if (r_refdef.fog_density)
6667         {
6668                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6669                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6670                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6671
6672                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6673                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6674                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6675                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6676
6677                 {
6678                         vec3_t fogvec;
6679                         VectorCopy(r_refdef.fogcolor, fogvec);
6680                         //   color.rgb *= ContrastBoost * SceneBrightness;
6681                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6682                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6683                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6684                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6685                 }
6686         }
6687 }
6688
6689 void R_UpdateVariables(void)
6690 {
6691         R_Textures_Frame();
6692
6693         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6694
6695         r_refdef.farclip = r_farclip_base.value;
6696         if (r_refdef.scene.worldmodel)
6697                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6698         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6699
6700         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6701                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6702         r_refdef.polygonfactor = 0;
6703         r_refdef.polygonoffset = 0;
6704         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6705         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6706
6707         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6708         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6709         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6710         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6711         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6712         if (FAKELIGHT_ENABLED)
6713         {
6714                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6715         }
6716         else if (r_refdef.scene.worldmodel)
6717         {
6718                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6719         }
6720         if (r_showsurfaces.integer)
6721         {
6722                 r_refdef.scene.rtworld = false;
6723                 r_refdef.scene.rtworldshadows = false;
6724                 r_refdef.scene.rtdlight = false;
6725                 r_refdef.scene.rtdlightshadows = false;
6726                 r_refdef.lightmapintensity = 0;
6727         }
6728
6729         switch(vid.renderpath)
6730         {
6731         case RENDERPATH_GL20:
6732         case RENDERPATH_D3D9:
6733         case RENDERPATH_D3D10:
6734         case RENDERPATH_D3D11:
6735         case RENDERPATH_SOFT:
6736         case RENDERPATH_GLES2:
6737                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6738                 {
6739                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6740                         {
6741                                 // build GLSL gamma texture
6742 #define RAMPWIDTH 256
6743                                 unsigned short ramp[RAMPWIDTH * 3];
6744                                 unsigned char rampbgr[RAMPWIDTH][4];
6745                                 int i;
6746
6747                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6748
6749                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6750                                 for(i = 0; i < RAMPWIDTH; ++i)
6751                                 {
6752                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6753                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6754                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6755                                         rampbgr[i][3] = 0;
6756                                 }
6757                                 if (r_texture_gammaramps)
6758                                 {
6759                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6760                                 }
6761                                 else
6762                                 {
6763                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6764                                 }
6765                         }
6766                 }
6767                 else
6768                 {
6769                         // remove GLSL gamma texture
6770                 }
6771                 break;
6772         case RENDERPATH_GL11:
6773         case RENDERPATH_GL13:
6774         case RENDERPATH_GLES1:
6775                 break;
6776         }
6777 }
6778
6779 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6780 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6781 /*
6782 ================
6783 R_SelectScene
6784 ================
6785 */
6786 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6787         if( scenetype != r_currentscenetype ) {
6788                 // store the old scenetype
6789                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6790                 r_currentscenetype = scenetype;
6791                 // move in the new scene
6792                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6793         }
6794 }
6795
6796 /*
6797 ================
6798 R_GetScenePointer
6799 ================
6800 */
6801 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6802 {
6803         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6804         if( scenetype == r_currentscenetype ) {
6805                 return &r_refdef.scene;
6806         } else {
6807                 return &r_scenes_store[ scenetype ];
6808         }
6809 }
6810
6811 static int R_SortEntities_Compare(const void *ap, const void *bp)
6812 {
6813         const entity_render_t *a = *(const entity_render_t **)ap;
6814         const entity_render_t *b = *(const entity_render_t **)bp;
6815
6816         // 1. compare model
6817         if(a->model < b->model)
6818                 return -1;
6819         if(a->model > b->model)
6820                 return +1;
6821
6822         // 2. compare skin
6823         // TODO possibly calculate the REAL skinnum here first using
6824         // skinscenes?
6825         if(a->skinnum < b->skinnum)
6826                 return -1;
6827         if(a->skinnum > b->skinnum)
6828                 return +1;
6829
6830         // everything we compared is equal
6831         return 0;
6832 }
6833 static void R_SortEntities(void)
6834 {
6835         // below or equal 2 ents, sorting never gains anything
6836         if(r_refdef.scene.numentities <= 2)
6837                 return;
6838         // sort
6839         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6840 }
6841
6842 /*
6843 ================
6844 R_RenderView
6845 ================
6846 */
6847 int dpsoftrast_test;
6848 extern cvar_t r_shadow_bouncegrid;
6849 void R_RenderView(void)
6850 {
6851         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6852         int fbo;
6853         rtexture_t *depthtexture;
6854         rtexture_t *colortexture;
6855
6856         dpsoftrast_test = r_test.integer;
6857
6858         if (r_timereport_active)
6859                 R_TimeReport("start");
6860         r_textureframe++; // used only by R_GetCurrentTexture
6861         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6862
6863         if(R_CompileShader_CheckStaticParms())
6864                 R_GLSL_Restart_f();
6865
6866         if (!r_drawentities.integer)
6867                 r_refdef.scene.numentities = 0;
6868         else if (r_sortentities.integer)
6869                 R_SortEntities();
6870
6871         R_AnimCache_ClearCache();
6872         R_FrameData_NewFrame();
6873
6874         /* adjust for stereo display */
6875         if(R_Stereo_Active())
6876         {
6877                 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);
6878                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6879         }
6880
6881         if (r_refdef.view.isoverlay)
6882         {
6883                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6884                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6885                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6886                 R_TimeReport("depthclear");
6887
6888                 r_refdef.view.showdebug = false;
6889
6890                 r_fb.water.enabled = false;
6891                 r_fb.water.numwaterplanes = 0;
6892
6893                 R_RenderScene(0, NULL, NULL);
6894
6895                 r_refdef.view.matrix = originalmatrix;
6896
6897                 CHECKGLERROR
6898                 return;
6899         }
6900
6901         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6902         {
6903                 r_refdef.view.matrix = originalmatrix;
6904                 return;
6905         }
6906
6907         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6908
6909         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6910                 // in sRGB fallback, behave similar to true sRGB: convert this
6911                 // value from linear to sRGB
6912                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6913
6914         R_RenderView_UpdateViewVectors();
6915
6916         R_Shadow_UpdateWorldLightSelection();
6917
6918         R_Bloom_StartFrame();
6919         R_Water_StartFrame();
6920
6921         // now we probably have an fbo to render into
6922         fbo = r_fb.fbo;
6923         depthtexture = r_fb.depthtexture;
6924         colortexture = r_fb.colortexture;
6925
6926         CHECKGLERROR
6927         if (r_timereport_active)
6928                 R_TimeReport("viewsetup");
6929
6930         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6931
6932         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6933         {
6934                 R_ClearScreen(r_refdef.fogenabled);
6935                 if (r_timereport_active)
6936                         R_TimeReport("viewclear");
6937         }
6938         r_refdef.view.clear = true;
6939
6940         r_refdef.view.showdebug = true;
6941
6942         R_View_Update();
6943         if (r_timereport_active)
6944                 R_TimeReport("visibility");
6945
6946         R_Shadow_UpdateBounceGridTexture();
6947         if (r_timereport_active && r_shadow_bouncegrid.integer)
6948                 R_TimeReport("bouncegrid");
6949
6950         r_fb.water.numwaterplanes = 0;
6951         if (r_fb.water.enabled)
6952                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6953
6954         R_RenderScene(fbo, depthtexture, colortexture);
6955         r_fb.water.numwaterplanes = 0;
6956
6957         R_BlendView(fbo, depthtexture, colortexture);
6958         if (r_timereport_active)
6959                 R_TimeReport("blendview");
6960
6961         GL_Scissor(0, 0, vid.width, vid.height);
6962         GL_ScissorTest(false);
6963
6964         r_refdef.view.matrix = originalmatrix;
6965
6966         CHECKGLERROR
6967 }
6968
6969 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6970 {
6971         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6972         {
6973                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6974                 if (r_timereport_active)
6975                         R_TimeReport("waterworld");
6976         }
6977
6978         // don't let sound skip if going slow
6979         if (r_refdef.scene.extraupdate)
6980                 S_ExtraUpdate ();
6981
6982         R_DrawModelsAddWaterPlanes();
6983         if (r_timereport_active)
6984                 R_TimeReport("watermodels");
6985
6986         if (r_fb.water.numwaterplanes)
6987         {
6988                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6989                 if (r_timereport_active)
6990                         R_TimeReport("waterscenes");
6991         }
6992 }
6993
6994 extern cvar_t cl_locs_show;
6995 static void R_DrawLocs(void);
6996 static void R_DrawEntityBBoxes(void);
6997 static void R_DrawModelDecals(void);
6998 extern cvar_t cl_decals_newsystem;
6999 extern qboolean r_shadow_usingdeferredprepass;
7000 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7001 {
7002         qboolean shadowmapping = false;
7003
7004         if (r_timereport_active)
7005                 R_TimeReport("beginscene");
7006
7007         r_refdef.stats.renders++;
7008
7009         R_UpdateFog();
7010
7011         // don't let sound skip if going slow
7012         if (r_refdef.scene.extraupdate)
7013                 S_ExtraUpdate ();
7014
7015         R_MeshQueue_BeginScene();
7016
7017         R_SkyStartFrame();
7018
7019         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);
7020
7021         if (r_timereport_active)
7022                 R_TimeReport("skystartframe");
7023
7024         if (cl.csqc_vidvars.drawworld)
7025         {
7026                 // don't let sound skip if going slow
7027                 if (r_refdef.scene.extraupdate)
7028                         S_ExtraUpdate ();
7029
7030                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7031                 {
7032                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7033                         if (r_timereport_active)
7034                                 R_TimeReport("worldsky");
7035                 }
7036
7037                 if (R_DrawBrushModelsSky() && r_timereport_active)
7038                         R_TimeReport("bmodelsky");
7039
7040                 if (skyrendermasked && skyrenderlater)
7041                 {
7042                         // we have to force off the water clipping plane while rendering sky
7043                         R_SetupView(false, fbo, depthtexture, colortexture);
7044                         R_Sky();
7045                         R_SetupView(true, fbo, depthtexture, colortexture);
7046                         if (r_timereport_active)
7047                                 R_TimeReport("sky");
7048                 }
7049         }
7050
7051         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7052         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7053                 R_Shadow_PrepareModelShadows();
7054         if (r_timereport_active)
7055                 R_TimeReport("preparelights");
7056
7057         if (R_Shadow_ShadowMappingEnabled())
7058                 shadowmapping = true;
7059
7060         if (r_shadow_usingdeferredprepass)
7061                 R_Shadow_DrawPrepass();
7062
7063         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7064         {
7065                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7066                 if (r_timereport_active)
7067                         R_TimeReport("worlddepth");
7068         }
7069         if (r_depthfirst.integer >= 2)
7070         {
7071                 R_DrawModelsDepth();
7072                 if (r_timereport_active)
7073                         R_TimeReport("modeldepth");
7074         }
7075
7076         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7077         {
7078                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7079                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7080                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7081                 // don't let sound skip if going slow
7082                 if (r_refdef.scene.extraupdate)
7083                         S_ExtraUpdate ();
7084         }
7085
7086         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7087         {
7088                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7089                 if (r_timereport_active)
7090                         R_TimeReport("world");
7091         }
7092
7093         // don't let sound skip if going slow
7094         if (r_refdef.scene.extraupdate)
7095                 S_ExtraUpdate ();
7096
7097         R_DrawModels();
7098         if (r_timereport_active)
7099                 R_TimeReport("models");
7100
7101         // don't let sound skip if going slow
7102         if (r_refdef.scene.extraupdate)
7103                 S_ExtraUpdate ();
7104
7105         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7106         {
7107                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7108                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7109                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7110                 // don't let sound skip if going slow
7111                 if (r_refdef.scene.extraupdate)
7112                         S_ExtraUpdate ();
7113         }
7114
7115         if (!r_shadow_usingdeferredprepass)
7116         {
7117                 R_Shadow_DrawLights();
7118                 if (r_timereport_active)
7119                         R_TimeReport("rtlights");
7120         }
7121
7122         // don't let sound skip if going slow
7123         if (r_refdef.scene.extraupdate)
7124                 S_ExtraUpdate ();
7125
7126         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7127         {
7128                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7129                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7130                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7131                 // don't let sound skip if going slow
7132                 if (r_refdef.scene.extraupdate)
7133                         S_ExtraUpdate ();
7134         }
7135
7136         if (cl.csqc_vidvars.drawworld)
7137         {
7138                 if (cl_decals_newsystem.integer)
7139                 {
7140                         R_DrawModelDecals();
7141                         if (r_timereport_active)
7142                                 R_TimeReport("modeldecals");
7143                 }
7144                 else
7145                 {
7146                         R_DrawDecals();
7147                         if (r_timereport_active)
7148                                 R_TimeReport("decals");
7149                 }
7150
7151                 R_DrawParticles();
7152                 if (r_timereport_active)
7153                         R_TimeReport("particles");
7154
7155                 R_DrawExplosions();
7156                 if (r_timereport_active)
7157                         R_TimeReport("explosions");
7158
7159                 R_DrawLightningBeams();
7160                 if (r_timereport_active)
7161                         R_TimeReport("lightning");
7162         }
7163
7164         if (cl.csqc_loaded)
7165                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7166
7167         if (r_refdef.view.showdebug)
7168         {
7169                 if (cl_locs_show.integer)
7170                 {
7171                         R_DrawLocs();
7172                         if (r_timereport_active)
7173                                 R_TimeReport("showlocs");
7174                 }
7175
7176                 if (r_drawportals.integer)
7177                 {
7178                         R_DrawPortals();
7179                         if (r_timereport_active)
7180                                 R_TimeReport("portals");
7181                 }
7182
7183                 if (r_showbboxes.value > 0)
7184                 {
7185                         R_DrawEntityBBoxes();
7186                         if (r_timereport_active)
7187                                 R_TimeReport("bboxes");
7188                 }
7189         }
7190
7191         if (r_transparent.integer)
7192         {
7193                 R_MeshQueue_RenderTransparent();
7194                 if (r_timereport_active)
7195                         R_TimeReport("drawtrans");
7196         }
7197
7198         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))
7199         {
7200                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7201                 if (r_timereport_active)
7202                         R_TimeReport("worlddebug");
7203                 R_DrawModelsDebug();
7204                 if (r_timereport_active)
7205                         R_TimeReport("modeldebug");
7206         }
7207
7208         if (cl.csqc_vidvars.drawworld)
7209         {
7210                 R_Shadow_DrawCoronas();
7211                 if (r_timereport_active)
7212                         R_TimeReport("coronas");
7213         }
7214
7215 #if 0
7216         {
7217                 GL_DepthTest(false);
7218                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7219                 GL_Color(1, 1, 1, 1);
7220                 qglBegin(GL_POLYGON);
7221                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7222                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7223                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7224                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7225                 qglEnd();
7226                 qglBegin(GL_POLYGON);
7227                 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]);
7228                 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]);
7229                 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]);
7230                 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]);
7231                 qglEnd();
7232                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7233         }
7234 #endif
7235
7236         // don't let sound skip if going slow
7237         if (r_refdef.scene.extraupdate)
7238                 S_ExtraUpdate ();
7239 }
7240
7241 static const unsigned short bboxelements[36] =
7242 {
7243         5, 1, 3, 5, 3, 7,
7244         6, 2, 0, 6, 0, 4,
7245         7, 3, 2, 7, 2, 6,
7246         4, 0, 1, 4, 1, 5,
7247         4, 5, 7, 4, 7, 6,
7248         1, 0, 2, 1, 2, 3,
7249 };
7250
7251 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7252 {
7253         int i;
7254         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7255
7256         RSurf_ActiveWorldEntity();
7257
7258         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7259         GL_DepthMask(false);
7260         GL_DepthRange(0, 1);
7261         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7262 //      R_Mesh_ResetTextureState();
7263
7264         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7265         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7266         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7267         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7268         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7269         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7270         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7271         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7272         R_FillColors(color4f, 8, cr, cg, cb, ca);
7273         if (r_refdef.fogenabled)
7274         {
7275                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7276                 {
7277                         f1 = RSurf_FogVertex(v);
7278                         f2 = 1 - f1;
7279                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7280                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7281                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7282                 }
7283         }
7284         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7285         R_Mesh_ResetTextureState();
7286         R_SetupShader_Generic_NoTexture(false, false);
7287         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7288 }
7289
7290 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7291 {
7292         prvm_prog_t *prog = SVVM_prog;
7293         int i;
7294         float color[4];
7295         prvm_edict_t *edict;
7296
7297         // this function draws bounding boxes of server entities
7298         if (!sv.active)
7299                 return;
7300
7301         GL_CullFace(GL_NONE);
7302         R_SetupShader_Generic_NoTexture(false, false);
7303
7304         for (i = 0;i < numsurfaces;i++)
7305         {
7306                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7307                 switch ((int)PRVM_serveredictfloat(edict, solid))
7308                 {
7309                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7310                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7311                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7312                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7313                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7314                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7315                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7316                 }
7317                 color[3] *= r_showbboxes.value;
7318                 color[3] = bound(0, color[3], 1);
7319                 GL_DepthTest(!r_showdisabledepthtest.integer);
7320                 GL_CullFace(r_refdef.view.cullface_front);
7321                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7322         }
7323 }
7324
7325 static void R_DrawEntityBBoxes(void)
7326 {
7327         int i;
7328         prvm_edict_t *edict;
7329         vec3_t center;
7330         prvm_prog_t *prog = SVVM_prog;
7331
7332         // this function draws bounding boxes of server entities
7333         if (!sv.active)
7334                 return;
7335
7336         for (i = 0;i < prog->num_edicts;i++)
7337         {
7338                 edict = PRVM_EDICT_NUM(i);
7339                 if (edict->priv.server->free)
7340                         continue;
7341                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7342                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7343                         continue;
7344                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7345                         continue;
7346                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7347                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7348         }
7349 }
7350
7351 static const int nomodelelement3i[24] =
7352 {
7353         5, 2, 0,
7354         5, 1, 2,
7355         5, 0, 3,
7356         5, 3, 1,
7357         0, 2, 4,
7358         2, 1, 4,
7359         3, 0, 4,
7360         1, 3, 4
7361 };
7362
7363 static const unsigned short nomodelelement3s[24] =
7364 {
7365         5, 2, 0,
7366         5, 1, 2,
7367         5, 0, 3,
7368         5, 3, 1,
7369         0, 2, 4,
7370         2, 1, 4,
7371         3, 0, 4,
7372         1, 3, 4
7373 };
7374
7375 static const float nomodelvertex3f[6*3] =
7376 {
7377         -16,   0,   0,
7378          16,   0,   0,
7379           0, -16,   0,
7380           0,  16,   0,
7381           0,   0, -16,
7382           0,   0,  16
7383 };
7384
7385 static const float nomodelcolor4f[6*4] =
7386 {
7387         0.0f, 0.0f, 0.5f, 1.0f,
7388         0.0f, 0.0f, 0.5f, 1.0f,
7389         0.0f, 0.5f, 0.0f, 1.0f,
7390         0.0f, 0.5f, 0.0f, 1.0f,
7391         0.5f, 0.0f, 0.0f, 1.0f,
7392         0.5f, 0.0f, 0.0f, 1.0f
7393 };
7394
7395 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7396 {
7397         int i;
7398         float f1, f2, *c;
7399         float color4f[6*4];
7400
7401         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);
7402
7403         // this is only called once per entity so numsurfaces is always 1, and
7404         // surfacelist is always {0}, so this code does not handle batches
7405
7406         if (rsurface.ent_flags & RENDER_ADDITIVE)
7407         {
7408                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7409                 GL_DepthMask(false);
7410         }
7411         else if (rsurface.colormod[3] < 1)
7412         {
7413                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7414                 GL_DepthMask(false);
7415         }
7416         else
7417         {
7418                 GL_BlendFunc(GL_ONE, GL_ZERO);
7419                 GL_DepthMask(true);
7420         }
7421         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7422         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7423         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7424         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7425         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7426         for (i = 0, c = color4f;i < 6;i++, c += 4)
7427         {
7428                 c[0] *= rsurface.colormod[0];
7429                 c[1] *= rsurface.colormod[1];
7430                 c[2] *= rsurface.colormod[2];
7431                 c[3] *= rsurface.colormod[3];
7432         }
7433         if (r_refdef.fogenabled)
7434         {
7435                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7436                 {
7437                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7438                         f2 = 1 - f1;
7439                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7440                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7441                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7442                 }
7443         }
7444 //      R_Mesh_ResetTextureState();
7445         R_SetupShader_Generic_NoTexture(false, false);
7446         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7447         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7448 }
7449
7450 void R_DrawNoModel(entity_render_t *ent)
7451 {
7452         vec3_t org;
7453         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7454         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7455                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7456         else
7457                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7458 }
7459
7460 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7461 {
7462         vec3_t right1, right2, diff, normal;
7463
7464         VectorSubtract (org2, org1, normal);
7465
7466         // calculate 'right' vector for start
7467         VectorSubtract (r_refdef.view.origin, org1, diff);
7468         CrossProduct (normal, diff, right1);
7469         VectorNormalize (right1);
7470
7471         // calculate 'right' vector for end
7472         VectorSubtract (r_refdef.view.origin, org2, diff);
7473         CrossProduct (normal, diff, right2);
7474         VectorNormalize (right2);
7475
7476         vert[ 0] = org1[0] + width * right1[0];
7477         vert[ 1] = org1[1] + width * right1[1];
7478         vert[ 2] = org1[2] + width * right1[2];
7479         vert[ 3] = org1[0] - width * right1[0];
7480         vert[ 4] = org1[1] - width * right1[1];
7481         vert[ 5] = org1[2] - width * right1[2];
7482         vert[ 6] = org2[0] - width * right2[0];
7483         vert[ 7] = org2[1] - width * right2[1];
7484         vert[ 8] = org2[2] - width * right2[2];
7485         vert[ 9] = org2[0] + width * right2[0];
7486         vert[10] = org2[1] + width * right2[1];
7487         vert[11] = org2[2] + width * right2[2];
7488 }
7489
7490 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)
7491 {
7492         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7493         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7494         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7495         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7496         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7497         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7498         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7499         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7500         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7501         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7502         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7503         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7504 }
7505
7506 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7507 {
7508         int i;
7509         float *vertex3f;
7510         float v[3];
7511         VectorSet(v, x, y, z);
7512         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7513                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7514                         break;
7515         if (i == mesh->numvertices)
7516         {
7517                 if (mesh->numvertices < mesh->maxvertices)
7518                 {
7519                         VectorCopy(v, vertex3f);
7520                         mesh->numvertices++;
7521                 }
7522                 return mesh->numvertices;
7523         }
7524         else
7525                 return i;
7526 }
7527
7528 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7529 {
7530         int i;
7531         int *e, element[3];
7532         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7533         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7534         e = mesh->element3i + mesh->numtriangles * 3;
7535         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7536         {
7537                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7538                 if (mesh->numtriangles < mesh->maxtriangles)
7539                 {
7540                         *e++ = element[0];
7541                         *e++ = element[1];
7542                         *e++ = element[2];
7543                         mesh->numtriangles++;
7544                 }
7545                 element[1] = element[2];
7546         }
7547 }
7548
7549 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7550 {
7551         int i;
7552         int *e, element[3];
7553         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7554         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7555         e = mesh->element3i + mesh->numtriangles * 3;
7556         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7557         {
7558                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7559                 if (mesh->numtriangles < mesh->maxtriangles)
7560                 {
7561                         *e++ = element[0];
7562                         *e++ = element[1];
7563                         *e++ = element[2];
7564                         mesh->numtriangles++;
7565                 }
7566                 element[1] = element[2];
7567         }
7568 }
7569
7570 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7571 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7572 {
7573         int planenum, planenum2;
7574         int w;
7575         int tempnumpoints;
7576         mplane_t *plane, *plane2;
7577         double maxdist;
7578         double temppoints[2][256*3];
7579         // figure out how large a bounding box we need to properly compute this brush
7580         maxdist = 0;
7581         for (w = 0;w < numplanes;w++)
7582                 maxdist = max(maxdist, fabs(planes[w].dist));
7583         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7584         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7585         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7586         {
7587                 w = 0;
7588                 tempnumpoints = 4;
7589                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7590                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7591                 {
7592                         if (planenum2 == planenum)
7593                                 continue;
7594                         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);
7595                         w = !w;
7596                 }
7597                 if (tempnumpoints < 3)
7598                         continue;
7599                 // generate elements forming a triangle fan for this polygon
7600                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7601         }
7602 }
7603
7604 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)
7605 {
7606         texturelayer_t *layer;
7607         layer = t->currentlayers + t->currentnumlayers++;
7608         layer->type = type;
7609         layer->depthmask = depthmask;
7610         layer->blendfunc1 = blendfunc1;
7611         layer->blendfunc2 = blendfunc2;
7612         layer->texture = texture;
7613         layer->texmatrix = *matrix;
7614         layer->color[0] = r;
7615         layer->color[1] = g;
7616         layer->color[2] = b;
7617         layer->color[3] = a;
7618 }
7619
7620 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7621 {
7622         if(parms[0] == 0 && parms[1] == 0)
7623                 return false;
7624         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7625                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7626                         return false;
7627         return true;
7628 }
7629
7630 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7631 {
7632         double index, f;
7633         index = parms[2] + rsurface.shadertime * parms[3];
7634         index -= floor(index);
7635         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7636         {
7637         default:
7638         case Q3WAVEFUNC_NONE:
7639         case Q3WAVEFUNC_NOISE:
7640         case Q3WAVEFUNC_COUNT:
7641                 f = 0;
7642                 break;
7643         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7644         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7645         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7646         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7647         case Q3WAVEFUNC_TRIANGLE:
7648                 index *= 4;
7649                 f = index - floor(index);
7650                 if (index < 1)
7651                 {
7652                         // f = f;
7653                 }
7654                 else if (index < 2)
7655                         f = 1 - f;
7656                 else if (index < 3)
7657                         f = -f;
7658                 else
7659                         f = -(1 - f);
7660                 break;
7661         }
7662         f = parms[0] + parms[1] * f;
7663         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7664                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7665         return (float) f;
7666 }
7667
7668 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7669 {
7670         int w, h, idx;
7671         double f;
7672         double offsetd[2];
7673         float tcmat[12];
7674         matrix4x4_t matrix, temp;
7675         switch(tcmod->tcmod)
7676         {
7677                 case Q3TCMOD_COUNT:
7678                 case Q3TCMOD_NONE:
7679                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7680                                 matrix = r_waterscrollmatrix;
7681                         else
7682                                 matrix = identitymatrix;
7683                         break;
7684                 case Q3TCMOD_ENTITYTRANSLATE:
7685                         // this is used in Q3 to allow the gamecode to control texcoord
7686                         // scrolling on the entity, which is not supported in darkplaces yet.
7687                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7688                         break;
7689                 case Q3TCMOD_ROTATE:
7690                         f = tcmod->parms[0] * rsurface.shadertime;
7691                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7692                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7693                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7694                         break;
7695                 case Q3TCMOD_SCALE:
7696                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7697                         break;
7698                 case Q3TCMOD_SCROLL:
7699                         // extra care is needed because of precision breakdown with large values of time
7700                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7701                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7702                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7703                         break;
7704                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7705                         w = (int) tcmod->parms[0];
7706                         h = (int) tcmod->parms[1];
7707                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7708                         f = f - floor(f);
7709                         idx = (int) floor(f * w * h);
7710                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7711                         break;
7712                 case Q3TCMOD_STRETCH:
7713                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7714                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7715                         break;
7716                 case Q3TCMOD_TRANSFORM:
7717                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7718                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7719                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7720                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7721                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7722                         break;
7723                 case Q3TCMOD_TURBULENT:
7724                         // this is handled in the RSurf_PrepareVertices function
7725                         matrix = identitymatrix;
7726                         break;
7727         }
7728         temp = *texmatrix;
7729         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7730 }
7731
7732 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7733 {
7734         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7735         char name[MAX_QPATH];
7736         skinframe_t *skinframe;
7737         unsigned char pixels[296*194];
7738         strlcpy(cache->name, skinname, sizeof(cache->name));
7739         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7740         if (developer_loading.integer)
7741                 Con_Printf("loading %s\n", name);
7742         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7743         if (!skinframe || !skinframe->base)
7744         {
7745                 unsigned char *f;
7746                 fs_offset_t filesize;
7747                 skinframe = NULL;
7748                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7749                 if (f)
7750                 {
7751                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7752                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7753                         Mem_Free(f);
7754                 }
7755         }
7756         cache->skinframe = skinframe;
7757 }
7758
7759 texture_t *R_GetCurrentTexture(texture_t *t)
7760 {
7761         int i;
7762         const entity_render_t *ent = rsurface.entity;
7763         dp_model_t *model = ent->model;
7764         q3shaderinfo_layer_tcmod_t *tcmod;
7765
7766         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7767                 return t->currentframe;
7768         t->update_lastrenderframe = r_textureframe;
7769         t->update_lastrenderentity = (void *)ent;
7770
7771         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7772                 t->camera_entity = ent->entitynumber;
7773         else
7774                 t->camera_entity = 0;
7775
7776         // switch to an alternate material if this is a q1bsp animated material
7777         {
7778                 texture_t *texture = t;
7779                 int s = rsurface.ent_skinnum;
7780                 if ((unsigned int)s >= (unsigned int)model->numskins)
7781                         s = 0;
7782                 if (model->skinscenes)
7783                 {
7784                         if (model->skinscenes[s].framecount > 1)
7785                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7786                         else
7787                                 s = model->skinscenes[s].firstframe;
7788                 }
7789                 if (s > 0)
7790                         t = t + s * model->num_surfaces;
7791                 if (t->animated)
7792                 {
7793                         // use an alternate animation if the entity's frame is not 0,
7794                         // and only if the texture has an alternate animation
7795                         if (rsurface.ent_alttextures && t->anim_total[1])
7796                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7797                         else
7798                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7799                 }
7800                 texture->currentframe = t;
7801         }
7802
7803         // update currentskinframe to be a qw skin or animation frame
7804         if (rsurface.ent_qwskin >= 0)
7805         {
7806                 i = rsurface.ent_qwskin;
7807                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7808                 {
7809                         r_qwskincache_size = cl.maxclients;
7810                         if (r_qwskincache)
7811                                 Mem_Free(r_qwskincache);
7812                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7813                 }
7814                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7815                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7816                 t->currentskinframe = r_qwskincache[i].skinframe;
7817                 if (t->currentskinframe == NULL)
7818                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7819         }
7820         else if (t->numskinframes >= 2)
7821                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7822         if (t->backgroundnumskinframes >= 2)
7823                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7824
7825         t->currentmaterialflags = t->basematerialflags;
7826         t->currentalpha = rsurface.colormod[3];
7827         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7828                 t->currentalpha *= r_wateralpha.value;
7829         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7830                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7831         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7832                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7833         if (!(rsurface.ent_flags & RENDER_LIGHT))
7834                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7835         else if (FAKELIGHT_ENABLED)
7836         {
7837                 // no modellight if using fakelight for the map
7838         }
7839         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7840         {
7841                 // pick a model lighting mode
7842                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7843                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7844                 else
7845                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7846         }
7847         if (rsurface.ent_flags & RENDER_ADDITIVE)
7848                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7849         else if (t->currentalpha < 1)
7850                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7851         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7852         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7853                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7854         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7855                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7856         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7857                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7858         if (t->backgroundnumskinframes)
7859                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7860         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7861         {
7862                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7863                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7864         }
7865         else
7866                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7867         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7868         {
7869                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7870                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7871         }
7872         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7873                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7874
7875         // there is no tcmod
7876         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7877         {
7878                 t->currenttexmatrix = r_waterscrollmatrix;
7879                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7880         }
7881         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7882         {
7883                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7884                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7885         }
7886
7887         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7888                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7889         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7890                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7891
7892         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7893         if (t->currentskinframe->qpixels)
7894                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7895         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7896         if (!t->basetexture)
7897                 t->basetexture = r_texture_notexture;
7898         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7899         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7900         t->nmaptexture = t->currentskinframe->nmap;
7901         if (!t->nmaptexture)
7902                 t->nmaptexture = r_texture_blanknormalmap;
7903         t->glosstexture = r_texture_black;
7904         t->glowtexture = t->currentskinframe->glow;
7905         t->fogtexture = t->currentskinframe->fog;
7906         t->reflectmasktexture = t->currentskinframe->reflect;
7907         if (t->backgroundnumskinframes)
7908         {
7909                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7910                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7911                 t->backgroundglosstexture = r_texture_black;
7912                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7913                 if (!t->backgroundnmaptexture)
7914                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7915                 // make sure that if glow is going to be used, both textures are not NULL
7916                 if (!t->backgroundglowtexture && t->glowtexture)
7917                         t->backgroundglowtexture = r_texture_black;
7918                 if (!t->glowtexture && t->backgroundglowtexture)
7919                         t->glowtexture = r_texture_black;
7920         }
7921         else
7922         {
7923                 t->backgroundbasetexture = r_texture_white;
7924                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7925                 t->backgroundglosstexture = r_texture_black;
7926                 t->backgroundglowtexture = NULL;
7927         }
7928         t->specularpower = r_shadow_glossexponent.value;
7929         // TODO: store reference values for these in the texture?
7930         t->specularscale = 0;
7931         if (r_shadow_gloss.integer > 0)
7932         {
7933                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7934                 {
7935                         if (r_shadow_glossintensity.value > 0)
7936                         {
7937                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7938                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7939                                 t->specularscale = r_shadow_glossintensity.value;
7940                         }
7941                 }
7942                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7943                 {
7944                         t->glosstexture = r_texture_white;
7945                         t->backgroundglosstexture = r_texture_white;
7946                         t->specularscale = r_shadow_gloss2intensity.value;
7947                         t->specularpower = r_shadow_gloss2exponent.value;
7948                 }
7949         }
7950         t->specularscale *= t->specularscalemod;
7951         t->specularpower *= t->specularpowermod;
7952         t->rtlightambient = 0;
7953
7954         // lightmaps mode looks bad with dlights using actual texturing, so turn
7955         // off the colormap and glossmap, but leave the normalmap on as it still
7956         // accurately represents the shading involved
7957         if (gl_lightmaps.integer)
7958         {
7959                 t->basetexture = r_texture_grey128;
7960                 t->pantstexture = r_texture_black;
7961                 t->shirttexture = r_texture_black;
7962                 t->nmaptexture = r_texture_blanknormalmap;
7963                 t->glosstexture = r_texture_black;
7964                 t->glowtexture = NULL;
7965                 t->fogtexture = NULL;
7966                 t->reflectmasktexture = NULL;
7967                 t->backgroundbasetexture = NULL;
7968                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7969                 t->backgroundglosstexture = r_texture_black;
7970                 t->backgroundglowtexture = NULL;
7971                 t->specularscale = 0;
7972                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7973         }
7974
7975         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7976         VectorClear(t->dlightcolor);
7977         t->currentnumlayers = 0;
7978         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7979         {
7980                 int blendfunc1, blendfunc2;
7981                 qboolean depthmask;
7982                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7983                 {
7984                         blendfunc1 = GL_SRC_ALPHA;
7985                         blendfunc2 = GL_ONE;
7986                 }
7987                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7988                 {
7989                         blendfunc1 = GL_SRC_ALPHA;
7990                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7991                 }
7992                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7993                 {
7994                         blendfunc1 = t->customblendfunc[0];
7995                         blendfunc2 = t->customblendfunc[1];
7996                 }
7997                 else
7998                 {
7999                         blendfunc1 = GL_ONE;
8000                         blendfunc2 = GL_ZERO;
8001                 }
8002                 // don't colormod evilblend textures
8003                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8004                         VectorSet(t->lightmapcolor, 1, 1, 1);
8005                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8006                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8007                 {
8008                         // fullbright is not affected by r_refdef.lightmapintensity
8009                         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]);
8010                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8011                                 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]);
8012                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8013                                 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]);
8014                 }
8015                 else
8016                 {
8017                         vec3_t ambientcolor;
8018                         float colorscale;
8019                         // set the color tint used for lights affecting this surface
8020                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8021                         colorscale = 2;
8022                         // q3bsp has no lightmap updates, so the lightstylevalue that
8023                         // would normally be baked into the lightmap must be
8024                         // applied to the color
8025                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8026                         if (model->type == mod_brushq3)
8027                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8028                         colorscale *= r_refdef.lightmapintensity;
8029                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8030                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8031                         // basic lit geometry
8032                         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]);
8033                         // add pants/shirt if needed
8034                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8035                                 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]);
8036                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8037                                 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]);
8038                         // now add ambient passes if needed
8039                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8040                         {
8041                                 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]);
8042                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8043                                         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]);
8044                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8045                                         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]);
8046                         }
8047                 }
8048                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8049                         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]);
8050                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8051                 {
8052                         // if this is opaque use alpha blend which will darken the earlier
8053                         // passes cheaply.
8054                         //
8055                         // if this is an alpha blended material, all the earlier passes
8056                         // were darkened by fog already, so we only need to add the fog
8057                         // color ontop through the fog mask texture
8058                         //
8059                         // if this is an additive blended material, all the earlier passes
8060                         // were darkened by fog already, and we should not add fog color
8061                         // (because the background was not darkened, there is no fog color
8062                         // that was lost behind it).
8063                         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]);
8064                 }
8065         }
8066
8067         return t->currentframe;
8068 }
8069
8070 rsurfacestate_t rsurface;
8071
8072 void RSurf_ActiveWorldEntity(void)
8073 {
8074         dp_model_t *model = r_refdef.scene.worldmodel;
8075         //if (rsurface.entity == r_refdef.scene.worldentity)
8076         //      return;
8077         rsurface.entity = r_refdef.scene.worldentity;
8078         rsurface.skeleton = NULL;
8079         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8080         rsurface.ent_skinnum = 0;
8081         rsurface.ent_qwskin = -1;
8082         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8083         rsurface.shadertime = r_refdef.scene.time;
8084         rsurface.matrix = identitymatrix;
8085         rsurface.inversematrix = identitymatrix;
8086         rsurface.matrixscale = 1;
8087         rsurface.inversematrixscale = 1;
8088         R_EntityMatrix(&identitymatrix);
8089         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8090         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8091         rsurface.fograngerecip = r_refdef.fograngerecip;
8092         rsurface.fogheightfade = r_refdef.fogheightfade;
8093         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8094         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8095         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8096         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8097         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8098         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8099         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8100         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8101         rsurface.colormod[3] = 1;
8102         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);
8103         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8104         rsurface.frameblend[0].lerp = 1;
8105         rsurface.ent_alttextures = false;
8106         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8107         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8108         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8109         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8110         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8111         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8112         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8113         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8114         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8115         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8116         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8117         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8118         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8119         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8120         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8121         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8122         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8123         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8124         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8126         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8127         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8129         rsurface.modelelement3i = model->surfmesh.data_element3i;
8130         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8131         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8132         rsurface.modelelement3s = model->surfmesh.data_element3s;
8133         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8134         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8135         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8136         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8137         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8138         rsurface.modelsurfaces = model->data_surfaces;
8139         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8140         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8141         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8142         rsurface.modelgeneratedvertex = false;
8143         rsurface.batchgeneratedvertex = false;
8144         rsurface.batchfirstvertex = 0;
8145         rsurface.batchnumvertices = 0;
8146         rsurface.batchfirsttriangle = 0;
8147         rsurface.batchnumtriangles = 0;
8148         rsurface.batchvertex3f  = NULL;
8149         rsurface.batchvertex3f_vertexbuffer = NULL;
8150         rsurface.batchvertex3f_bufferoffset = 0;
8151         rsurface.batchsvector3f = NULL;
8152         rsurface.batchsvector3f_vertexbuffer = NULL;
8153         rsurface.batchsvector3f_bufferoffset = 0;
8154         rsurface.batchtvector3f = NULL;
8155         rsurface.batchtvector3f_vertexbuffer = NULL;
8156         rsurface.batchtvector3f_bufferoffset = 0;
8157         rsurface.batchnormal3f  = NULL;
8158         rsurface.batchnormal3f_vertexbuffer = NULL;
8159         rsurface.batchnormal3f_bufferoffset = 0;
8160         rsurface.batchlightmapcolor4f = NULL;
8161         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8162         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8163         rsurface.batchtexcoordtexture2f = NULL;
8164         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8165         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8166         rsurface.batchtexcoordlightmap2f = NULL;
8167         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8168         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8169         rsurface.batchvertexmesh = NULL;
8170         rsurface.batchvertexmeshbuffer = NULL;
8171         rsurface.batchvertex3fbuffer = NULL;
8172         rsurface.batchelement3i = NULL;
8173         rsurface.batchelement3i_indexbuffer = NULL;
8174         rsurface.batchelement3i_bufferoffset = 0;
8175         rsurface.batchelement3s = NULL;
8176         rsurface.batchelement3s_indexbuffer = NULL;
8177         rsurface.batchelement3s_bufferoffset = 0;
8178         rsurface.passcolor4f = NULL;
8179         rsurface.passcolor4f_vertexbuffer = NULL;
8180         rsurface.passcolor4f_bufferoffset = 0;
8181 }
8182
8183 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8184 {
8185         dp_model_t *model = ent->model;
8186         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8187         //      return;
8188         rsurface.entity = (entity_render_t *)ent;
8189         rsurface.skeleton = ent->skeleton;
8190         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8191         rsurface.ent_skinnum = ent->skinnum;
8192         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;
8193         rsurface.ent_flags = ent->flags;
8194         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8195         rsurface.matrix = ent->matrix;
8196         rsurface.inversematrix = ent->inversematrix;
8197         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8198         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8199         R_EntityMatrix(&rsurface.matrix);
8200         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8201         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8202         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8203         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8204         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8205         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8206         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8207         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8208         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8209         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8210         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8211         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8212         rsurface.colormod[3] = ent->alpha;
8213         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8214         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8215         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8216         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8217         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8218         if (ent->model->brush.submodel && !prepass)
8219         {
8220                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8221                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8222         }
8223         if (model->surfmesh.isanimated && model->AnimateVertices)
8224         {
8225                 if (ent->animcache_vertex3f)
8226                 {
8227                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8228                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8229                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8230                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8231                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8232                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8233                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8234                 }
8235                 else if (wanttangents)
8236                 {
8237                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8238                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8239                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8240                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8241                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8242                         rsurface.modelvertexmesh = NULL;
8243                         rsurface.modelvertexmeshbuffer = NULL;
8244                         rsurface.modelvertex3fbuffer = NULL;
8245                 }
8246                 else if (wantnormals)
8247                 {
8248                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8249                         rsurface.modelsvector3f = NULL;
8250                         rsurface.modeltvector3f = NULL;
8251                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8252                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8253                         rsurface.modelvertexmesh = NULL;
8254                         rsurface.modelvertexmeshbuffer = NULL;
8255                         rsurface.modelvertex3fbuffer = NULL;
8256                 }
8257                 else
8258                 {
8259                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8260                         rsurface.modelsvector3f = NULL;
8261                         rsurface.modeltvector3f = NULL;
8262                         rsurface.modelnormal3f = NULL;
8263                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8264                         rsurface.modelvertexmesh = NULL;
8265                         rsurface.modelvertexmeshbuffer = NULL;
8266                         rsurface.modelvertex3fbuffer = NULL;
8267                 }
8268                 rsurface.modelvertex3f_vertexbuffer = 0;
8269                 rsurface.modelvertex3f_bufferoffset = 0;
8270                 rsurface.modelsvector3f_vertexbuffer = 0;
8271                 rsurface.modelsvector3f_bufferoffset = 0;
8272                 rsurface.modeltvector3f_vertexbuffer = 0;
8273                 rsurface.modeltvector3f_bufferoffset = 0;
8274                 rsurface.modelnormal3f_vertexbuffer = 0;
8275                 rsurface.modelnormal3f_bufferoffset = 0;
8276                 rsurface.modelgeneratedvertex = true;
8277         }
8278         else
8279         {
8280                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8281                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8282                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8283                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8284                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8285                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8286                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8287                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8288                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8289                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8290                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8291                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8292                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8293                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8294                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8295                 rsurface.modelgeneratedvertex = false;
8296         }
8297         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8298         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8299         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8300         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8301         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8302         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8303         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8304         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8305         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8306         rsurface.modelelement3i = model->surfmesh.data_element3i;
8307         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8308         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8309         rsurface.modelelement3s = model->surfmesh.data_element3s;
8310         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8311         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8312         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8313         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8314         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8315         rsurface.modelsurfaces = model->data_surfaces;
8316         rsurface.batchgeneratedvertex = false;
8317         rsurface.batchfirstvertex = 0;
8318         rsurface.batchnumvertices = 0;
8319         rsurface.batchfirsttriangle = 0;
8320         rsurface.batchnumtriangles = 0;
8321         rsurface.batchvertex3f  = NULL;
8322         rsurface.batchvertex3f_vertexbuffer = NULL;
8323         rsurface.batchvertex3f_bufferoffset = 0;
8324         rsurface.batchsvector3f = NULL;
8325         rsurface.batchsvector3f_vertexbuffer = NULL;
8326         rsurface.batchsvector3f_bufferoffset = 0;
8327         rsurface.batchtvector3f = NULL;
8328         rsurface.batchtvector3f_vertexbuffer = NULL;
8329         rsurface.batchtvector3f_bufferoffset = 0;
8330         rsurface.batchnormal3f  = NULL;
8331         rsurface.batchnormal3f_vertexbuffer = NULL;
8332         rsurface.batchnormal3f_bufferoffset = 0;
8333         rsurface.batchlightmapcolor4f = NULL;
8334         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8335         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8336         rsurface.batchtexcoordtexture2f = NULL;
8337         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8338         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8339         rsurface.batchtexcoordlightmap2f = NULL;
8340         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8341         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8342         rsurface.batchvertexmesh = NULL;
8343         rsurface.batchvertexmeshbuffer = NULL;
8344         rsurface.batchvertex3fbuffer = NULL;
8345         rsurface.batchelement3i = NULL;
8346         rsurface.batchelement3i_indexbuffer = NULL;
8347         rsurface.batchelement3i_bufferoffset = 0;
8348         rsurface.batchelement3s = NULL;
8349         rsurface.batchelement3s_indexbuffer = NULL;
8350         rsurface.batchelement3s_bufferoffset = 0;
8351         rsurface.passcolor4f = NULL;
8352         rsurface.passcolor4f_vertexbuffer = NULL;
8353         rsurface.passcolor4f_bufferoffset = 0;
8354 }
8355
8356 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)
8357 {
8358         rsurface.entity = r_refdef.scene.worldentity;
8359         rsurface.skeleton = NULL;
8360         rsurface.ent_skinnum = 0;
8361         rsurface.ent_qwskin = -1;
8362         rsurface.ent_flags = entflags;
8363         rsurface.shadertime = r_refdef.scene.time - shadertime;
8364         rsurface.modelnumvertices = numvertices;
8365         rsurface.modelnumtriangles = numtriangles;
8366         rsurface.matrix = *matrix;
8367         rsurface.inversematrix = *inversematrix;
8368         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8369         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8370         R_EntityMatrix(&rsurface.matrix);
8371         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8372         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8373         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8374         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8375         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8376         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8377         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8378         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8379         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8380         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8381         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8382         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8383         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);
8384         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8385         rsurface.frameblend[0].lerp = 1;
8386         rsurface.ent_alttextures = false;
8387         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8388         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8389         if (wanttangents)
8390         {
8391                 rsurface.modelvertex3f = (float *)vertex3f;
8392                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8393                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8394                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8395         }
8396         else if (wantnormals)
8397         {
8398                 rsurface.modelvertex3f = (float *)vertex3f;
8399                 rsurface.modelsvector3f = NULL;
8400                 rsurface.modeltvector3f = NULL;
8401                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8402         }
8403         else
8404         {
8405                 rsurface.modelvertex3f = (float *)vertex3f;
8406                 rsurface.modelsvector3f = NULL;
8407                 rsurface.modeltvector3f = NULL;
8408                 rsurface.modelnormal3f = NULL;
8409         }
8410         rsurface.modelvertexmesh = NULL;
8411         rsurface.modelvertexmeshbuffer = NULL;
8412         rsurface.modelvertex3fbuffer = NULL;
8413         rsurface.modelvertex3f_vertexbuffer = 0;
8414         rsurface.modelvertex3f_bufferoffset = 0;
8415         rsurface.modelsvector3f_vertexbuffer = 0;
8416         rsurface.modelsvector3f_bufferoffset = 0;
8417         rsurface.modeltvector3f_vertexbuffer = 0;
8418         rsurface.modeltvector3f_bufferoffset = 0;
8419         rsurface.modelnormal3f_vertexbuffer = 0;
8420         rsurface.modelnormal3f_bufferoffset = 0;
8421         rsurface.modelgeneratedvertex = true;
8422         rsurface.modellightmapcolor4f  = (float *)color4f;
8423         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8424         rsurface.modellightmapcolor4f_bufferoffset = 0;
8425         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8426         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8427         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8428         rsurface.modeltexcoordlightmap2f  = NULL;
8429         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8430         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8431         rsurface.modelelement3i = (int *)element3i;
8432         rsurface.modelelement3i_indexbuffer = NULL;
8433         rsurface.modelelement3i_bufferoffset = 0;
8434         rsurface.modelelement3s = (unsigned short *)element3s;
8435         rsurface.modelelement3s_indexbuffer = NULL;
8436         rsurface.modelelement3s_bufferoffset = 0;
8437         rsurface.modellightmapoffsets = NULL;
8438         rsurface.modelsurfaces = NULL;
8439         rsurface.batchgeneratedvertex = false;
8440         rsurface.batchfirstvertex = 0;
8441         rsurface.batchnumvertices = 0;
8442         rsurface.batchfirsttriangle = 0;
8443         rsurface.batchnumtriangles = 0;
8444         rsurface.batchvertex3f  = NULL;
8445         rsurface.batchvertex3f_vertexbuffer = NULL;
8446         rsurface.batchvertex3f_bufferoffset = 0;
8447         rsurface.batchsvector3f = NULL;
8448         rsurface.batchsvector3f_vertexbuffer = NULL;
8449         rsurface.batchsvector3f_bufferoffset = 0;
8450         rsurface.batchtvector3f = NULL;
8451         rsurface.batchtvector3f_vertexbuffer = NULL;
8452         rsurface.batchtvector3f_bufferoffset = 0;
8453         rsurface.batchnormal3f  = NULL;
8454         rsurface.batchnormal3f_vertexbuffer = NULL;
8455         rsurface.batchnormal3f_bufferoffset = 0;
8456         rsurface.batchlightmapcolor4f = NULL;
8457         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8458         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8459         rsurface.batchtexcoordtexture2f = NULL;
8460         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8461         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8462         rsurface.batchtexcoordlightmap2f = NULL;
8463         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8464         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8465         rsurface.batchvertexmesh = NULL;
8466         rsurface.batchvertexmeshbuffer = NULL;
8467         rsurface.batchvertex3fbuffer = NULL;
8468         rsurface.batchelement3i = NULL;
8469         rsurface.batchelement3i_indexbuffer = NULL;
8470         rsurface.batchelement3i_bufferoffset = 0;
8471         rsurface.batchelement3s = NULL;
8472         rsurface.batchelement3s_indexbuffer = NULL;
8473         rsurface.batchelement3s_bufferoffset = 0;
8474         rsurface.passcolor4f = NULL;
8475         rsurface.passcolor4f_vertexbuffer = NULL;
8476         rsurface.passcolor4f_bufferoffset = 0;
8477
8478         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8479         {
8480                 if ((wantnormals || wanttangents) && !normal3f)
8481                 {
8482                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8483                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8484                 }
8485                 if (wanttangents && !svector3f)
8486                 {
8487                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8488                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8489                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8490                 }
8491         }
8492 }
8493
8494 float RSurf_FogPoint(const float *v)
8495 {
8496         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8497         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8498         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8499         float FogHeightFade = r_refdef.fogheightfade;
8500         float fogfrac;
8501         unsigned int fogmasktableindex;
8502         if (r_refdef.fogplaneviewabove)
8503                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8504         else
8505                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8506         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8507         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8508 }
8509
8510 float RSurf_FogVertex(const float *v)
8511 {
8512         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8513         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8514         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8515         float FogHeightFade = rsurface.fogheightfade;
8516         float fogfrac;
8517         unsigned int fogmasktableindex;
8518         if (r_refdef.fogplaneviewabove)
8519                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8520         else
8521                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8522         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8523         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8524 }
8525
8526 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8527 {
8528         int i;
8529         for (i = 0;i < numelements;i++)
8530                 outelement3i[i] = inelement3i[i] + adjust;
8531 }
8532
8533 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8534 extern cvar_t gl_vbo;
8535 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8536 {
8537         int deformindex;
8538         int firsttriangle;
8539         int numtriangles;
8540         int firstvertex;
8541         int endvertex;
8542         int numvertices;
8543         int surfacefirsttriangle;
8544         int surfacenumtriangles;
8545         int surfacefirstvertex;
8546         int surfaceendvertex;
8547         int surfacenumvertices;
8548         int batchnumvertices;
8549         int batchnumtriangles;
8550         int needsupdate;
8551         int i, j;
8552         qboolean gaps;
8553         qboolean dynamicvertex;
8554         float amplitude;
8555         float animpos;
8556         float scale;
8557         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8558         float waveparms[4];
8559         q3shaderinfo_deform_t *deform;
8560         const msurface_t *surface, *firstsurface;
8561         r_vertexmesh_t *vertexmesh;
8562         if (!texturenumsurfaces)
8563                 return;
8564         // find vertex range of this surface batch
8565         gaps = false;
8566         firstsurface = texturesurfacelist[0];
8567         firsttriangle = firstsurface->num_firsttriangle;
8568         batchnumvertices = 0;
8569         batchnumtriangles = 0;
8570         firstvertex = endvertex = firstsurface->num_firstvertex;
8571         for (i = 0;i < texturenumsurfaces;i++)
8572         {
8573                 surface = texturesurfacelist[i];
8574                 if (surface != firstsurface + i)
8575                         gaps = true;
8576                 surfacefirstvertex = surface->num_firstvertex;
8577                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8578                 surfacenumvertices = surface->num_vertices;
8579                 surfacenumtriangles = surface->num_triangles;
8580                 if (firstvertex > surfacefirstvertex)
8581                         firstvertex = surfacefirstvertex;
8582                 if (endvertex < surfaceendvertex)
8583                         endvertex = surfaceendvertex;
8584                 batchnumvertices += surfacenumvertices;
8585                 batchnumtriangles += surfacenumtriangles;
8586         }
8587
8588         // we now know the vertex range used, and if there are any gaps in it
8589         rsurface.batchfirstvertex = firstvertex;
8590         rsurface.batchnumvertices = endvertex - firstvertex;
8591         rsurface.batchfirsttriangle = firsttriangle;
8592         rsurface.batchnumtriangles = batchnumtriangles;
8593
8594         // this variable holds flags for which properties have been updated that
8595         // may require regenerating vertexmesh array...
8596         needsupdate = 0;
8597
8598         // check if any dynamic vertex processing must occur
8599         dynamicvertex = false;
8600
8601         // if there is a chance of animated vertex colors, it's a dynamic batch
8602         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8603         {
8604                 dynamicvertex = true;
8605                 batchneed |= BATCHNEED_NOGAPS;
8606                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8607         }
8608
8609         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8610         {
8611                 switch (deform->deform)
8612                 {
8613                 default:
8614                 case Q3DEFORM_PROJECTIONSHADOW:
8615                 case Q3DEFORM_TEXT0:
8616                 case Q3DEFORM_TEXT1:
8617                 case Q3DEFORM_TEXT2:
8618                 case Q3DEFORM_TEXT3:
8619                 case Q3DEFORM_TEXT4:
8620                 case Q3DEFORM_TEXT5:
8621                 case Q3DEFORM_TEXT6:
8622                 case Q3DEFORM_TEXT7:
8623                 case Q3DEFORM_NONE:
8624                         break;
8625                 case Q3DEFORM_AUTOSPRITE:
8626                         dynamicvertex = true;
8627                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8628                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8629                         break;
8630                 case Q3DEFORM_AUTOSPRITE2:
8631                         dynamicvertex = true;
8632                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8633                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8634                         break;
8635                 case Q3DEFORM_NORMAL:
8636                         dynamicvertex = true;
8637                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8638                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8639                         break;
8640                 case Q3DEFORM_WAVE:
8641                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8642                                 break; // if wavefunc is a nop, ignore this transform
8643                         dynamicvertex = true;
8644                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8645                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8646                         break;
8647                 case Q3DEFORM_BULGE:
8648                         dynamicvertex = true;
8649                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8650                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8651                         break;
8652                 case Q3DEFORM_MOVE:
8653                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8654                                 break; // if wavefunc is a nop, ignore this transform
8655                         dynamicvertex = true;
8656                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8657                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8658                         break;
8659                 }
8660         }
8661         switch(rsurface.texture->tcgen.tcgen)
8662         {
8663         default:
8664         case Q3TCGEN_TEXTURE:
8665                 break;
8666         case Q3TCGEN_LIGHTMAP:
8667                 dynamicvertex = true;
8668                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8669                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8670                 break;
8671         case Q3TCGEN_VECTOR:
8672                 dynamicvertex = true;
8673                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8674                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8675                 break;
8676         case Q3TCGEN_ENVIRONMENT:
8677                 dynamicvertex = true;
8678                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8679                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8680                 break;
8681         }
8682         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8683         {
8684                 dynamicvertex = true;
8685                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8686                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8687         }
8688
8689         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8690         {
8691                 dynamicvertex = true;
8692                 batchneed |= BATCHNEED_NOGAPS;
8693                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8694         }
8695
8696         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8697         {
8698                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8699                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8700                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8701                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8702                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8703                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8704                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8705         }
8706
8707         // when the model data has no vertex buffer (dynamic mesh), we need to
8708         // eliminate gaps
8709         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8710                 batchneed |= BATCHNEED_NOGAPS;
8711
8712         // if needsupdate, we have to do a dynamic vertex batch for sure
8713         if (needsupdate & batchneed)
8714                 dynamicvertex = true;
8715
8716         // see if we need to build vertexmesh from arrays
8717         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8718                 dynamicvertex = true;
8719
8720         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8721         // also some drivers strongly dislike firstvertex
8722         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8723                 dynamicvertex = true;
8724
8725         rsurface.batchvertex3f = rsurface.modelvertex3f;
8726         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8727         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8728         rsurface.batchsvector3f = rsurface.modelsvector3f;
8729         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8730         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8731         rsurface.batchtvector3f = rsurface.modeltvector3f;
8732         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8733         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8734         rsurface.batchnormal3f = rsurface.modelnormal3f;
8735         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8736         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8737         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8738         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8739         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8740         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8741         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8742         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8743         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8744         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8745         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8746         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8747         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8748         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8749         rsurface.batchelement3i = rsurface.modelelement3i;
8750         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8751         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8752         rsurface.batchelement3s = rsurface.modelelement3s;
8753         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8754         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8755
8756         // if any dynamic vertex processing has to occur in software, we copy the
8757         // entire surface list together before processing to rebase the vertices
8758         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8759         //
8760         // if any gaps exist and we do not have a static vertex buffer, we have to
8761         // copy the surface list together to avoid wasting upload bandwidth on the
8762         // vertices in the gaps.
8763         //
8764         // if gaps exist and we have a static vertex buffer, we still have to
8765         // combine the index buffer ranges into one dynamic index buffer.
8766         //
8767         // in all cases we end up with data that can be drawn in one call.
8768
8769         if (!dynamicvertex)
8770         {
8771                 // static vertex data, just set pointers...
8772                 rsurface.batchgeneratedvertex = false;
8773                 // if there are gaps, we want to build a combined index buffer,
8774                 // otherwise use the original static buffer with an appropriate offset
8775                 if (gaps)
8776                 {
8777                         // build a new triangle elements array for this batch
8778                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8779                         rsurface.batchfirsttriangle = 0;
8780                         numtriangles = 0;
8781                         for (i = 0;i < texturenumsurfaces;i++)
8782                         {
8783                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8784                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8785                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8786                                 numtriangles += surfacenumtriangles;
8787                         }
8788                         rsurface.batchelement3i_indexbuffer = NULL;
8789                         rsurface.batchelement3i_bufferoffset = 0;
8790                         rsurface.batchelement3s = NULL;
8791                         rsurface.batchelement3s_indexbuffer = NULL;
8792                         rsurface.batchelement3s_bufferoffset = 0;
8793                         if (endvertex <= 65536)
8794                         {
8795                                 // make a 16bit (unsigned short) index array if possible
8796                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8797                                 for (i = 0;i < numtriangles*3;i++)
8798                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8799                         }
8800                 }
8801                 return;
8802         }
8803
8804         // something needs software processing, do it for real...
8805         // we only directly handle separate array data in this case and then
8806         // generate interleaved data if needed...
8807         rsurface.batchgeneratedvertex = true;
8808
8809         // now copy the vertex data into a combined array and make an index array
8810         // (this is what Quake3 does all the time)
8811         //if (gaps || rsurface.batchfirstvertex)
8812         {
8813                 rsurface.batchvertex3fbuffer = NULL;
8814                 rsurface.batchvertexmesh = NULL;
8815                 rsurface.batchvertexmeshbuffer = NULL;
8816                 rsurface.batchvertex3f = NULL;
8817                 rsurface.batchvertex3f_vertexbuffer = NULL;
8818                 rsurface.batchvertex3f_bufferoffset = 0;
8819                 rsurface.batchsvector3f = NULL;
8820                 rsurface.batchsvector3f_vertexbuffer = NULL;
8821                 rsurface.batchsvector3f_bufferoffset = 0;
8822                 rsurface.batchtvector3f = NULL;
8823                 rsurface.batchtvector3f_vertexbuffer = NULL;
8824                 rsurface.batchtvector3f_bufferoffset = 0;
8825                 rsurface.batchnormal3f = NULL;
8826                 rsurface.batchnormal3f_vertexbuffer = NULL;
8827                 rsurface.batchnormal3f_bufferoffset = 0;
8828                 rsurface.batchlightmapcolor4f = NULL;
8829                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8830                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8831                 rsurface.batchtexcoordtexture2f = NULL;
8832                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8833                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8834                 rsurface.batchtexcoordlightmap2f = NULL;
8835                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8836                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8837                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8838                 rsurface.batchelement3i_indexbuffer = NULL;
8839                 rsurface.batchelement3i_bufferoffset = 0;
8840                 rsurface.batchelement3s = NULL;
8841                 rsurface.batchelement3s_indexbuffer = NULL;
8842                 rsurface.batchelement3s_bufferoffset = 0;
8843                 // we'll only be setting up certain arrays as needed
8844                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8845                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8846                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8847                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8848                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8849                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8850                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8851                 {
8852                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8853                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8854                 }
8855                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8856                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8857                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8858                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8859                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8860                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8861                 numvertices = 0;
8862                 numtriangles = 0;
8863                 for (i = 0;i < texturenumsurfaces;i++)
8864                 {
8865                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8866                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8867                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8868                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8869                         // copy only the data requested
8870                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8871                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8872                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8873                         {
8874                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8875                                 {
8876                                         if (rsurface.batchvertex3f)
8877                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8878                                         else
8879                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8880                                 }
8881                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8882                                 {
8883                                         if (rsurface.modelnormal3f)
8884                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8885                                         else
8886                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8887                                 }
8888                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8889                                 {
8890                                         if (rsurface.modelsvector3f)
8891                                         {
8892                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8893                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8894                                         }
8895                                         else
8896                                         {
8897                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8898                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8899                                         }
8900                                 }
8901                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8902                                 {
8903                                         if (rsurface.modellightmapcolor4f)
8904                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8905                                         else
8906                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8907                                 }
8908                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8909                                 {
8910                                         if (rsurface.modeltexcoordtexture2f)
8911                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8912                                         else
8913                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8914                                 }
8915                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8916                                 {
8917                                         if (rsurface.modeltexcoordlightmap2f)
8918                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8919                                         else
8920                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8921                                 }
8922                         }
8923                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8924                         numvertices += surfacenumvertices;
8925                         numtriangles += surfacenumtriangles;
8926                 }
8927
8928                 // generate a 16bit index array as well if possible
8929                 // (in general, dynamic batches fit)
8930                 if (numvertices <= 65536)
8931                 {
8932                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8933                         for (i = 0;i < numtriangles*3;i++)
8934                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8935                 }
8936
8937                 // since we've copied everything, the batch now starts at 0
8938                 rsurface.batchfirstvertex = 0;
8939                 rsurface.batchnumvertices = batchnumvertices;
8940                 rsurface.batchfirsttriangle = 0;
8941                 rsurface.batchnumtriangles = batchnumtriangles;
8942         }
8943
8944         // q1bsp surfaces rendered in vertex color mode have to have colors
8945         // calculated based on lightstyles
8946         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8947         {
8948                 // generate color arrays for the surfaces in this list
8949                 int c[4];
8950                 int scale;
8951                 int size3;
8952                 const int *offsets;
8953                 const unsigned char *lm;
8954                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8955                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8956                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8957                 numvertices = 0;
8958                 for (i = 0;i < texturenumsurfaces;i++)
8959                 {
8960                         surface = texturesurfacelist[i];
8961                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8962                         surfacenumvertices = surface->num_vertices;
8963                         if (surface->lightmapinfo->samples)
8964                         {
8965                                 for (j = 0;j < surfacenumvertices;j++)
8966                                 {
8967                                         lm = surface->lightmapinfo->samples + offsets[j];
8968                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8969                                         VectorScale(lm, scale, c);
8970                                         if (surface->lightmapinfo->styles[1] != 255)
8971                                         {
8972                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8973                                                 lm += size3;
8974                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8975                                                 VectorMA(c, scale, lm, c);
8976                                                 if (surface->lightmapinfo->styles[2] != 255)
8977                                                 {
8978                                                         lm += size3;
8979                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8980                                                         VectorMA(c, scale, lm, c);
8981                                                         if (surface->lightmapinfo->styles[3] != 255)
8982                                                         {
8983                                                                 lm += size3;
8984                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8985                                                                 VectorMA(c, scale, lm, c);
8986                                                         }
8987                                                 }
8988                                         }
8989                                         c[0] >>= 7;
8990                                         c[1] >>= 7;
8991                                         c[2] >>= 7;
8992                                         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);
8993                                         numvertices++;
8994                                 }
8995                         }
8996                         else
8997                         {
8998                                 for (j = 0;j < surfacenumvertices;j++)
8999                                 {
9000                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9001                                         numvertices++;
9002                                 }
9003                         }
9004                 }
9005         }
9006
9007         // if vertices are deformed (sprite flares and things in maps, possibly
9008         // water waves, bulges and other deformations), modify the copied vertices
9009         // in place
9010         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9011         {
9012                 switch (deform->deform)
9013                 {
9014                 default:
9015                 case Q3DEFORM_PROJECTIONSHADOW:
9016                 case Q3DEFORM_TEXT0:
9017                 case Q3DEFORM_TEXT1:
9018                 case Q3DEFORM_TEXT2:
9019                 case Q3DEFORM_TEXT3:
9020                 case Q3DEFORM_TEXT4:
9021                 case Q3DEFORM_TEXT5:
9022                 case Q3DEFORM_TEXT6:
9023                 case Q3DEFORM_TEXT7:
9024                 case Q3DEFORM_NONE:
9025                         break;
9026                 case Q3DEFORM_AUTOSPRITE:
9027                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9028                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9029                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9030                         VectorNormalize(newforward);
9031                         VectorNormalize(newright);
9032                         VectorNormalize(newup);
9033 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9034 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9035 //                      rsurface.batchvertex3f_bufferoffset = 0;
9036 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9037 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9038 //                      rsurface.batchsvector3f_bufferoffset = 0;
9039 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9040 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9041 //                      rsurface.batchtvector3f_bufferoffset = 0;
9042 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9043 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9044 //                      rsurface.batchnormal3f_bufferoffset = 0;
9045                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9046                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9047                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9048                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9049                                 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);
9050                         // a single autosprite surface can contain multiple sprites...
9051                         for (j = 0;j < batchnumvertices - 3;j += 4)
9052                         {
9053                                 VectorClear(center);
9054                                 for (i = 0;i < 4;i++)
9055                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9056                                 VectorScale(center, 0.25f, center);
9057                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9058                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9059                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9060                                 for (i = 0;i < 4;i++)
9061                                 {
9062                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9063                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9064                                 }
9065                         }
9066                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9067                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9068                         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);
9069                         break;
9070                 case Q3DEFORM_AUTOSPRITE2:
9071                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9072                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9073                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9074                         VectorNormalize(newforward);
9075                         VectorNormalize(newright);
9076                         VectorNormalize(newup);
9077 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9078 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9079 //                      rsurface.batchvertex3f_bufferoffset = 0;
9080                         {
9081                                 const float *v1, *v2;
9082                                 vec3_t start, end;
9083                                 float f, l;
9084                                 struct
9085                                 {
9086                                         float length2;
9087                                         const float *v1;
9088                                         const float *v2;
9089                                 }
9090                                 shortest[2];
9091                                 memset(shortest, 0, sizeof(shortest));
9092                                 // a single autosprite surface can contain multiple sprites...
9093                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9094                                 {
9095                                         VectorClear(center);
9096                                         for (i = 0;i < 4;i++)
9097                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9098                                         VectorScale(center, 0.25f, center);
9099                                         // find the two shortest edges, then use them to define the
9100                                         // axis vectors for rotating around the central axis
9101                                         for (i = 0;i < 6;i++)
9102                                         {
9103                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9104                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9105                                                 l = VectorDistance2(v1, v2);
9106                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9107                                                 if (v1[2] != v2[2])
9108                                                         l += (1.0f / 1024.0f);
9109                                                 if (shortest[0].length2 > l || i == 0)
9110                                                 {
9111                                                         shortest[1] = shortest[0];
9112                                                         shortest[0].length2 = l;
9113                                                         shortest[0].v1 = v1;
9114                                                         shortest[0].v2 = v2;
9115                                                 }
9116                                                 else if (shortest[1].length2 > l || i == 1)
9117                                                 {
9118                                                         shortest[1].length2 = l;
9119                                                         shortest[1].v1 = v1;
9120                                                         shortest[1].v2 = v2;
9121                                                 }
9122                                         }
9123                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9124                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9125                                         // this calculates the right vector from the shortest edge
9126                                         // and the up vector from the edge midpoints
9127                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9128                                         VectorNormalize(right);
9129                                         VectorSubtract(end, start, up);
9130                                         VectorNormalize(up);
9131                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9132                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9133                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9134                                         VectorNegate(forward, forward);
9135                                         VectorReflect(forward, 0, up, forward);
9136                                         VectorNormalize(forward);
9137                                         CrossProduct(up, forward, newright);
9138                                         VectorNormalize(newright);
9139                                         // rotate the quad around the up axis vector, this is made
9140                                         // especially easy by the fact we know the quad is flat,
9141                                         // so we only have to subtract the center position and
9142                                         // measure distance along the right vector, and then
9143                                         // multiply that by the newright vector and add back the
9144                                         // center position
9145                                         // we also need to subtract the old position to undo the
9146                                         // displacement from the center, which we do with a
9147                                         // DotProduct, the subtraction/addition of center is also
9148                                         // optimized into DotProducts here
9149                                         l = DotProduct(right, center);
9150                                         for (i = 0;i < 4;i++)
9151                                         {
9152                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9153                                                 f = DotProduct(right, v1) - l;
9154                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9155                                         }
9156                                 }
9157                         }
9158                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9159                         {
9160 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9161 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9162 //                              rsurface.batchnormal3f_bufferoffset = 0;
9163                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9164                         }
9165                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9166                         {
9167 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9168 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9169 //                              rsurface.batchsvector3f_bufferoffset = 0;
9170 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9171 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9172 //                              rsurface.batchtvector3f_bufferoffset = 0;
9173                                 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);
9174                         }
9175                         break;
9176                 case Q3DEFORM_NORMAL:
9177                         // deform the normals to make reflections wavey
9178                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9179                         rsurface.batchnormal3f_vertexbuffer = NULL;
9180                         rsurface.batchnormal3f_bufferoffset = 0;
9181                         for (j = 0;j < batchnumvertices;j++)
9182                         {
9183                                 float vertex[3];
9184                                 float *normal = rsurface.batchnormal3f + 3*j;
9185                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9186                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9187                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9188                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9189                                 VectorNormalize(normal);
9190                         }
9191                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9192                         {
9193 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9194 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9195 //                              rsurface.batchsvector3f_bufferoffset = 0;
9196 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9197 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9198 //                              rsurface.batchtvector3f_bufferoffset = 0;
9199                                 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);
9200                         }
9201                         break;
9202                 case Q3DEFORM_WAVE:
9203                         // deform vertex array to make wavey water and flags and such
9204                         waveparms[0] = deform->waveparms[0];
9205                         waveparms[1] = deform->waveparms[1];
9206                         waveparms[2] = deform->waveparms[2];
9207                         waveparms[3] = deform->waveparms[3];
9208                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9209                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9210                         // this is how a divisor of vertex influence on deformation
9211                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9212                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9213 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9214 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9215 //                      rsurface.batchvertex3f_bufferoffset = 0;
9216 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9217 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9218 //                      rsurface.batchnormal3f_bufferoffset = 0;
9219                         for (j = 0;j < batchnumvertices;j++)
9220                         {
9221                                 // if the wavefunc depends on time, evaluate it per-vertex
9222                                 if (waveparms[3])
9223                                 {
9224                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9225                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9226                                 }
9227                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9228                         }
9229                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9230                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9231                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9232                         {
9233 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9234 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9235 //                              rsurface.batchsvector3f_bufferoffset = 0;
9236 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9237 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9238 //                              rsurface.batchtvector3f_bufferoffset = 0;
9239                                 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);
9240                         }
9241                         break;
9242                 case Q3DEFORM_BULGE:
9243                         // deform vertex array to make the surface have moving bulges
9244 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9245 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9246 //                      rsurface.batchvertex3f_bufferoffset = 0;
9247 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9248 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9249 //                      rsurface.batchnormal3f_bufferoffset = 0;
9250                         for (j = 0;j < batchnumvertices;j++)
9251                         {
9252                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9253                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9254                         }
9255                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9256                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9257                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9258                         {
9259 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9260 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9261 //                              rsurface.batchsvector3f_bufferoffset = 0;
9262 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9263 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9264 //                              rsurface.batchtvector3f_bufferoffset = 0;
9265                                 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);
9266                         }
9267                         break;
9268                 case Q3DEFORM_MOVE:
9269                         // deform vertex array
9270                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9271                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9272                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9273                         VectorScale(deform->parms, scale, waveparms);
9274 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9275 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9276 //                      rsurface.batchvertex3f_bufferoffset = 0;
9277                         for (j = 0;j < batchnumvertices;j++)
9278                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9279                         break;
9280                 }
9281         }
9282
9283         // generate texcoords based on the chosen texcoord source
9284         switch(rsurface.texture->tcgen.tcgen)
9285         {
9286         default:
9287         case Q3TCGEN_TEXTURE:
9288                 break;
9289         case Q3TCGEN_LIGHTMAP:
9290 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9291 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9292 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9293                 if (rsurface.batchtexcoordlightmap2f)
9294                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9295                 break;
9296         case Q3TCGEN_VECTOR:
9297 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9298 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9299 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9300                 for (j = 0;j < batchnumvertices;j++)
9301                 {
9302                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9303                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9304                 }
9305                 break;
9306         case Q3TCGEN_ENVIRONMENT:
9307                 // make environment reflections using a spheremap
9308                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9309                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9310                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9311                 for (j = 0;j < batchnumvertices;j++)
9312                 {
9313                         // identical to Q3A's method, but executed in worldspace so
9314                         // carried models can be shiny too
9315
9316                         float viewer[3], d, reflected[3], worldreflected[3];
9317
9318                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9319                         // VectorNormalize(viewer);
9320
9321                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9322
9323                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9324                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9325                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9326                         // note: this is proportinal to viewer, so we can normalize later
9327
9328                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9329                         VectorNormalize(worldreflected);
9330
9331                         // note: this sphere map only uses world x and z!
9332                         // so positive and negative y will LOOK THE SAME.
9333                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9334                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9335                 }
9336                 break;
9337         }
9338         // the only tcmod that needs software vertex processing is turbulent, so
9339         // check for it here and apply the changes if needed
9340         // and we only support that as the first one
9341         // (handling a mixture of turbulent and other tcmods would be problematic
9342         //  without punting it entirely to a software path)
9343         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9344         {
9345                 amplitude = rsurface.texture->tcmods[0].parms[1];
9346                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9347 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9348 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9349 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9350                 for (j = 0;j < batchnumvertices;j++)
9351                 {
9352                         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);
9353                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9354                 }
9355         }
9356
9357         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9358         {
9359                 // convert the modified arrays to vertex structs
9360 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9361 //              rsurface.batchvertexmeshbuffer = NULL;
9362                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9363                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9364                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9365                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9366                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9367                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9368                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9369                 {
9370                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9371                         {
9372                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9373                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9374                         }
9375                 }
9376                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9377                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9378                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9379                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9380                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9381                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9382                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9383                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9384                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9385         }
9386 }
9387
9388 void RSurf_DrawBatch(void)
9389 {
9390         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9391         // through the pipeline, killing it earlier in the pipeline would have
9392         // per-surface overhead rather than per-batch overhead, so it's best to
9393         // reject it here, before it hits glDraw.
9394         if (rsurface.batchnumtriangles == 0)
9395                 return;
9396 #if 0
9397         // batch debugging code
9398         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9399         {
9400                 int i;
9401                 int j;
9402                 int c;
9403                 const int *e;
9404                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9405                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9406                 {
9407                         c = e[i];
9408                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9409                         {
9410                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9411                                 {
9412                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9413                                                 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);
9414                                         break;
9415                                 }
9416                         }
9417                 }
9418         }
9419 #endif
9420         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);
9421 }
9422
9423 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9424 {
9425         // pick the closest matching water plane
9426         int planeindex, vertexindex, bestplaneindex = -1;
9427         float d, bestd;
9428         vec3_t vert;
9429         const float *v;
9430         r_waterstate_waterplane_t *p;
9431         qboolean prepared = false;
9432         bestd = 0;
9433         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9434         {
9435                 if(p->camera_entity != rsurface.texture->camera_entity)
9436                         continue;
9437                 d = 0;
9438                 if(!prepared)
9439                 {
9440                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9441                         prepared = true;
9442                         if(rsurface.batchnumvertices == 0)
9443                                 break;
9444                 }
9445                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9446                 {
9447                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9448                         d += fabs(PlaneDiff(vert, &p->plane));
9449                 }
9450                 if (bestd > d || bestplaneindex < 0)
9451                 {
9452                         bestd = d;
9453                         bestplaneindex = planeindex;
9454                 }
9455         }
9456         return bestplaneindex;
9457         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9458         // this situation though, as it might be better to render single larger
9459         // batches with useless stuff (backface culled for example) than to
9460         // render multiple smaller batches
9461 }
9462
9463 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9464 {
9465         int i;
9466         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9467         rsurface.passcolor4f_vertexbuffer = 0;
9468         rsurface.passcolor4f_bufferoffset = 0;
9469         for (i = 0;i < rsurface.batchnumvertices;i++)
9470                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9471 }
9472
9473 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9474 {
9475         int i;
9476         float f;
9477         const float *v;
9478         const float *c;
9479         float *c2;
9480         if (rsurface.passcolor4f)
9481         {
9482                 // generate color arrays
9483                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9484                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9485                 rsurface.passcolor4f_vertexbuffer = 0;
9486                 rsurface.passcolor4f_bufferoffset = 0;
9487                 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)
9488                 {
9489                         f = RSurf_FogVertex(v);
9490                         c2[0] = c[0] * f;
9491                         c2[1] = c[1] * f;
9492                         c2[2] = c[2] * f;
9493                         c2[3] = c[3];
9494                 }
9495         }
9496         else
9497         {
9498                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9499                 rsurface.passcolor4f_vertexbuffer = 0;
9500                 rsurface.passcolor4f_bufferoffset = 0;
9501                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9502                 {
9503                         f = RSurf_FogVertex(v);
9504                         c2[0] = f;
9505                         c2[1] = f;
9506                         c2[2] = f;
9507                         c2[3] = 1;
9508                 }
9509         }
9510 }
9511
9512 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9513 {
9514         int i;
9515         float f;
9516         const float *v;
9517         const float *c;
9518         float *c2;
9519         if (!rsurface.passcolor4f)
9520                 return;
9521         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9522         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9523         rsurface.passcolor4f_vertexbuffer = 0;
9524         rsurface.passcolor4f_bufferoffset = 0;
9525         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)
9526         {
9527                 f = RSurf_FogVertex(v);
9528                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9529                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9530                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9531                 c2[3] = c[3];
9532         }
9533 }
9534
9535 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9536 {
9537         int i;
9538         const float *c;
9539         float *c2;
9540         if (!rsurface.passcolor4f)
9541                 return;
9542         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9543         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9544         rsurface.passcolor4f_vertexbuffer = 0;
9545         rsurface.passcolor4f_bufferoffset = 0;
9546         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9547         {
9548                 c2[0] = c[0] * r;
9549                 c2[1] = c[1] * g;
9550                 c2[2] = c[2] * b;
9551                 c2[3] = c[3] * a;
9552         }
9553 }
9554
9555 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9556 {
9557         int i;
9558         const float *c;
9559         float *c2;
9560         if (!rsurface.passcolor4f)
9561                 return;
9562         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9563         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9564         rsurface.passcolor4f_vertexbuffer = 0;
9565         rsurface.passcolor4f_bufferoffset = 0;
9566         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9567         {
9568                 c2[0] = c[0] + r_refdef.scene.ambient;
9569                 c2[1] = c[1] + r_refdef.scene.ambient;
9570                 c2[2] = c[2] + r_refdef.scene.ambient;
9571                 c2[3] = c[3];
9572         }
9573 }
9574
9575 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9576 {
9577         // TODO: optimize
9578         rsurface.passcolor4f = NULL;
9579         rsurface.passcolor4f_vertexbuffer = 0;
9580         rsurface.passcolor4f_bufferoffset = 0;
9581         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9582         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9583         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9584         GL_Color(r, g, b, a);
9585         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9586         RSurf_DrawBatch();
9587 }
9588
9589 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9590 {
9591         // TODO: optimize applyfog && applycolor case
9592         // just apply fog if necessary, and tint the fog color array if necessary
9593         rsurface.passcolor4f = NULL;
9594         rsurface.passcolor4f_vertexbuffer = 0;
9595         rsurface.passcolor4f_bufferoffset = 0;
9596         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9597         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9598         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9599         GL_Color(r, g, b, a);
9600         RSurf_DrawBatch();
9601 }
9602
9603 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9604 {
9605         // TODO: optimize
9606         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9607         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9608         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9609         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9610         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9611         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9612         GL_Color(r, g, b, a);
9613         RSurf_DrawBatch();
9614 }
9615
9616 static void RSurf_DrawBatch_GL11_ClampColor(void)
9617 {
9618         int i;
9619         const float *c1;
9620         float *c2;
9621         if (!rsurface.passcolor4f)
9622                 return;
9623         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9624         {
9625                 c2[0] = bound(0.0f, c1[0], 1.0f);
9626                 c2[1] = bound(0.0f, c1[1], 1.0f);
9627                 c2[2] = bound(0.0f, c1[2], 1.0f);
9628                 c2[3] = bound(0.0f, c1[3], 1.0f);
9629         }
9630 }
9631
9632 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9633 {
9634         int i;
9635         float f;
9636         const float *v;
9637         const float *n;
9638         float *c;
9639         //vec3_t eyedir;
9640
9641         // fake shading
9642         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9643         rsurface.passcolor4f_vertexbuffer = 0;
9644         rsurface.passcolor4f_bufferoffset = 0;
9645         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)
9646         {
9647                 f = -DotProduct(r_refdef.view.forward, n);
9648                 f = max(0, f);
9649                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9650                 f *= r_refdef.lightmapintensity;
9651                 Vector4Set(c, f, f, f, 1);
9652         }
9653 }
9654
9655 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9656 {
9657         RSurf_DrawBatch_GL11_ApplyFakeLight();
9658         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9659         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9660         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9661         GL_Color(r, g, b, a);
9662         RSurf_DrawBatch();
9663 }
9664
9665 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9666 {
9667         int i;
9668         float f;
9669         float alpha;
9670         const float *v;
9671         const float *n;
9672         float *c;
9673         vec3_t ambientcolor;
9674         vec3_t diffusecolor;
9675         vec3_t lightdir;
9676         // TODO: optimize
9677         // model lighting
9678         VectorCopy(rsurface.modellight_lightdir, lightdir);
9679         f = 0.5f * r_refdef.lightmapintensity;
9680         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9681         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9682         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9683         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9684         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9685         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9686         alpha = *a;
9687         if (VectorLength2(diffusecolor) > 0)
9688         {
9689                 // q3-style directional shading
9690                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9691                 rsurface.passcolor4f_vertexbuffer = 0;
9692                 rsurface.passcolor4f_bufferoffset = 0;
9693                 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)
9694                 {
9695                         if ((f = DotProduct(n, lightdir)) > 0)
9696                                 VectorMA(ambientcolor, f, diffusecolor, c);
9697                         else
9698                                 VectorCopy(ambientcolor, c);
9699                         c[3] = alpha;
9700                 }
9701                 *r = 1;
9702                 *g = 1;
9703                 *b = 1;
9704                 *a = 1;
9705                 *applycolor = false;
9706         }
9707         else
9708         {
9709                 *r = ambientcolor[0];
9710                 *g = ambientcolor[1];
9711                 *b = ambientcolor[2];
9712                 rsurface.passcolor4f = NULL;
9713                 rsurface.passcolor4f_vertexbuffer = 0;
9714                 rsurface.passcolor4f_bufferoffset = 0;
9715         }
9716 }
9717
9718 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9719 {
9720         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9721         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9722         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9723         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9724         GL_Color(r, g, b, a);
9725         RSurf_DrawBatch();
9726 }
9727
9728 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9729 {
9730         int i;
9731         float f;
9732         const float *v;
9733         float *c;
9734
9735         // fake shading
9736         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9737         rsurface.passcolor4f_vertexbuffer = 0;
9738         rsurface.passcolor4f_bufferoffset = 0;
9739
9740         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9741         {
9742                 f = 1 - RSurf_FogVertex(v);
9743                 c[0] = r;
9744                 c[1] = g;
9745                 c[2] = b;
9746                 c[3] = f * a;
9747         }
9748 }
9749
9750 void RSurf_SetupDepthAndCulling(void)
9751 {
9752         // submodels are biased to avoid z-fighting with world surfaces that they
9753         // may be exactly overlapping (avoids z-fighting artifacts on certain
9754         // doors and things in Quake maps)
9755         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9756         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9757         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9758         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9759 }
9760
9761 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9762 {
9763         // transparent sky would be ridiculous
9764         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9765                 return;
9766         R_SetupShader_Generic_NoTexture(false, false);
9767         skyrenderlater = true;
9768         RSurf_SetupDepthAndCulling();
9769         GL_DepthMask(true);
9770         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9771         // skymasking on them, and Quake3 never did sky masking (unlike
9772         // software Quake and software Quake2), so disable the sky masking
9773         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9774         // and skymasking also looks very bad when noclipping outside the
9775         // level, so don't use it then either.
9776         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9777         {
9778                 R_Mesh_ResetTextureState();
9779                 if (skyrendermasked)
9780                 {
9781                         R_SetupShader_DepthOrShadow(false, false);
9782                         // depth-only (masking)
9783                         GL_ColorMask(0,0,0,0);
9784                         // just to make sure that braindead drivers don't draw
9785                         // anything despite that colormask...
9786                         GL_BlendFunc(GL_ZERO, GL_ONE);
9787                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9788                         if (rsurface.batchvertex3fbuffer)
9789                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9790                         else
9791                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9792                 }
9793                 else
9794                 {
9795                         R_SetupShader_Generic_NoTexture(false, false);
9796                         // fog sky
9797                         GL_BlendFunc(GL_ONE, GL_ZERO);
9798                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9799                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9800                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9801                 }
9802                 RSurf_DrawBatch();
9803                 if (skyrendermasked)
9804                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9805         }
9806         R_Mesh_ResetTextureState();
9807         GL_Color(1, 1, 1, 1);
9808 }
9809
9810 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9811 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9812 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9813 {
9814         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9815                 return;
9816         if (prepass)
9817         {
9818                 // render screenspace normalmap to texture
9819                 GL_DepthMask(true);
9820                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9821                 RSurf_DrawBatch();
9822                 return;
9823         }
9824
9825         // bind lightmap texture
9826
9827         // water/refraction/reflection/camera surfaces have to be handled specially
9828         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9829         {
9830                 int start, end, startplaneindex;
9831                 for (start = 0;start < texturenumsurfaces;start = end)
9832                 {
9833                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9834                         if(startplaneindex < 0)
9835                         {
9836                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9837                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9838                                 end = start + 1;
9839                                 continue;
9840                         }
9841                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9842                                 ;
9843                         // now that we have a batch using the same planeindex, render it
9844                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9845                         {
9846                                 // render water or distortion background
9847                                 GL_DepthMask(true);
9848                                 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);
9849                                 RSurf_DrawBatch();
9850                                 // blend surface on top
9851                                 GL_DepthMask(false);
9852                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9853                                 RSurf_DrawBatch();
9854                         }
9855                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9856                         {
9857                                 // render surface with reflection texture as input
9858                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9859                                 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);
9860                                 RSurf_DrawBatch();
9861                         }
9862                 }
9863                 return;
9864         }
9865
9866         // render surface batch normally
9867         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9868         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);
9869         RSurf_DrawBatch();
9870 }
9871
9872 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9873 {
9874         // OpenGL 1.3 path - anything not completely ancient
9875         qboolean applycolor;
9876         qboolean applyfog;
9877         int layerindex;
9878         const texturelayer_t *layer;
9879         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);
9880         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9881
9882         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9883         {
9884                 vec4_t layercolor;
9885                 int layertexrgbscale;
9886                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9887                 {
9888                         if (layerindex == 0)
9889                                 GL_AlphaTest(true);
9890                         else
9891                         {
9892                                 GL_AlphaTest(false);
9893                                 GL_DepthFunc(GL_EQUAL);
9894                         }
9895                 }
9896                 GL_DepthMask(layer->depthmask && writedepth);
9897                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9898                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9899                 {
9900                         layertexrgbscale = 4;
9901                         VectorScale(layer->color, 0.25f, layercolor);
9902                 }
9903                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9904                 {
9905                         layertexrgbscale = 2;
9906                         VectorScale(layer->color, 0.5f, layercolor);
9907                 }
9908                 else
9909                 {
9910                         layertexrgbscale = 1;
9911                         VectorScale(layer->color, 1.0f, layercolor);
9912                 }
9913                 layercolor[3] = layer->color[3];
9914                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9915                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9916                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9917                 switch (layer->type)
9918                 {
9919                 case TEXTURELAYERTYPE_LITTEXTURE:
9920                         // single-pass lightmapped texture with 2x rgbscale
9921                         R_Mesh_TexBind(0, r_texture_white);
9922                         R_Mesh_TexMatrix(0, NULL);
9923                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9924                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9925                         R_Mesh_TexBind(1, layer->texture);
9926                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9927                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9928                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9929                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9930                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9931                         else if (FAKELIGHT_ENABLED)
9932                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9933                         else if (rsurface.uselightmaptexture)
9934                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9935                         else
9936                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9937                         break;
9938                 case TEXTURELAYERTYPE_TEXTURE:
9939                         // singletexture unlit texture with transparency support
9940                         R_Mesh_TexBind(0, layer->texture);
9941                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9942                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9943                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9944                         R_Mesh_TexBind(1, 0);
9945                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9946                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9947                         break;
9948                 case TEXTURELAYERTYPE_FOG:
9949                         // singletexture fogging
9950                         if (layer->texture)
9951                         {
9952                                 R_Mesh_TexBind(0, layer->texture);
9953                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9954                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9955                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9956                         }
9957                         else
9958                         {
9959                                 R_Mesh_TexBind(0, 0);
9960                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9961                         }
9962                         R_Mesh_TexBind(1, 0);
9963                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9964                         // generate a color array for the fog pass
9965                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9966                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9967                         RSurf_DrawBatch();
9968                         break;
9969                 default:
9970                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9971                 }
9972         }
9973         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9974         {
9975                 GL_DepthFunc(GL_LEQUAL);
9976                 GL_AlphaTest(false);
9977         }
9978 }
9979
9980 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9981 {
9982         // OpenGL 1.1 - crusty old voodoo path
9983         qboolean applyfog;
9984         int layerindex;
9985         const texturelayer_t *layer;
9986         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);
9987         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9988
9989         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9990         {
9991                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9992                 {
9993                         if (layerindex == 0)
9994                                 GL_AlphaTest(true);
9995                         else
9996                         {
9997                                 GL_AlphaTest(false);
9998                                 GL_DepthFunc(GL_EQUAL);
9999                         }
10000                 }
10001                 GL_DepthMask(layer->depthmask && writedepth);
10002                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10003                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10004                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10005                 switch (layer->type)
10006                 {
10007                 case TEXTURELAYERTYPE_LITTEXTURE:
10008                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10009                         {
10010                                 // two-pass lit texture with 2x rgbscale
10011                                 // first the lightmap pass
10012                                 R_Mesh_TexBind(0, r_texture_white);
10013                                 R_Mesh_TexMatrix(0, NULL);
10014                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10015                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10016                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10017                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10018                                 else if (FAKELIGHT_ENABLED)
10019                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10020                                 else if (rsurface.uselightmaptexture)
10021                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10022                                 else
10023                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10024                                 // then apply the texture to it
10025                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10026                                 R_Mesh_TexBind(0, layer->texture);
10027                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10028                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10029                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10030                                 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);
10031                         }
10032                         else
10033                         {
10034                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10035                                 R_Mesh_TexBind(0, layer->texture);
10036                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10037                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10038                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10039                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10040                                         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);
10041                                 else
10042                                         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);
10043                         }
10044                         break;
10045                 case TEXTURELAYERTYPE_TEXTURE:
10046                         // singletexture unlit texture with transparency support
10047                         R_Mesh_TexBind(0, layer->texture);
10048                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10049                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10050                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10051                         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);
10052                         break;
10053                 case TEXTURELAYERTYPE_FOG:
10054                         // singletexture fogging
10055                         if (layer->texture)
10056                         {
10057                                 R_Mesh_TexBind(0, layer->texture);
10058                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10059                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10060                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10061                         }
10062                         else
10063                         {
10064                                 R_Mesh_TexBind(0, 0);
10065                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10066                         }
10067                         // generate a color array for the fog pass
10068                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10069                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10070                         RSurf_DrawBatch();
10071                         break;
10072                 default:
10073                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10074                 }
10075         }
10076         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10077         {
10078                 GL_DepthFunc(GL_LEQUAL);
10079                 GL_AlphaTest(false);
10080         }
10081 }
10082
10083 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10084 {
10085         int vi;
10086         int j;
10087         r_vertexgeneric_t *batchvertex;
10088         float c[4];
10089
10090 //      R_Mesh_ResetTextureState();
10091         R_SetupShader_Generic_NoTexture(false, false);
10092
10093         if(rsurface.texture && rsurface.texture->currentskinframe)
10094         {
10095                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10096                 c[3] *= rsurface.texture->currentalpha;
10097         }
10098         else
10099         {
10100                 c[0] = 1;
10101                 c[1] = 0;
10102                 c[2] = 1;
10103                 c[3] = 1;
10104         }
10105
10106         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10107         {
10108                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10109                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10110                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10111         }
10112
10113         // brighten it up (as texture value 127 means "unlit")
10114         c[0] *= 2 * r_refdef.view.colorscale;
10115         c[1] *= 2 * r_refdef.view.colorscale;
10116         c[2] *= 2 * r_refdef.view.colorscale;
10117
10118         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10119                 c[3] *= r_wateralpha.value;
10120
10121         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10122         {
10123                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10124                 GL_DepthMask(false);
10125         }
10126         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10127         {
10128                 GL_BlendFunc(GL_ONE, GL_ONE);
10129                 GL_DepthMask(false);
10130         }
10131         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10132         {
10133                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10134                 GL_DepthMask(false);
10135         }
10136         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10137         {
10138                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10139                 GL_DepthMask(false);
10140         }
10141         else
10142         {
10143                 GL_BlendFunc(GL_ONE, GL_ZERO);
10144                 GL_DepthMask(writedepth);
10145         }
10146
10147         if (r_showsurfaces.integer == 3)
10148         {
10149                 rsurface.passcolor4f = NULL;
10150
10151                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10152                 {
10153                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10154
10155                         rsurface.passcolor4f = NULL;
10156                         rsurface.passcolor4f_vertexbuffer = 0;
10157                         rsurface.passcolor4f_bufferoffset = 0;
10158                 }
10159                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10160                 {
10161                         qboolean applycolor = true;
10162                         float one = 1.0;
10163
10164                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10165
10166                         r_refdef.lightmapintensity = 1;
10167                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10168                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10169                 }
10170                 else if (FAKELIGHT_ENABLED)
10171                 {
10172                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10173
10174                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10175                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10176                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10177                 }
10178                 else
10179                 {
10180                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10181
10182                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10183                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10184                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10185                 }
10186
10187                 if(!rsurface.passcolor4f)
10188                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10189
10190                 RSurf_DrawBatch_GL11_ApplyAmbient();
10191                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10192                 if(r_refdef.fogenabled)
10193                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10194                 RSurf_DrawBatch_GL11_ClampColor();
10195
10196                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10197                 R_SetupShader_Generic_NoTexture(false, false);
10198                 RSurf_DrawBatch();
10199         }
10200         else if (!r_refdef.view.showdebug)
10201         {
10202                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10203                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10204                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10205                 {
10206                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10207                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10208                 }
10209                 R_Mesh_PrepareVertices_Generic_Unlock();
10210                 RSurf_DrawBatch();
10211         }
10212         else if (r_showsurfaces.integer == 4)
10213         {
10214                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10215                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10216                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10217                 {
10218                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10219                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10220                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10221                 }
10222                 R_Mesh_PrepareVertices_Generic_Unlock();
10223                 RSurf_DrawBatch();
10224         }
10225         else if (r_showsurfaces.integer == 2)
10226         {
10227                 const int *e;
10228                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10229                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10230                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10231                 {
10232                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10233                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10234                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10235                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10236                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10237                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10238                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10239                 }
10240                 R_Mesh_PrepareVertices_Generic_Unlock();
10241                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10242         }
10243         else
10244         {
10245                 int texturesurfaceindex;
10246                 int k;
10247                 const msurface_t *surface;
10248                 float surfacecolor4f[4];
10249                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10250                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10251                 vi = 0;
10252                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10253                 {
10254                         surface = texturesurfacelist[texturesurfaceindex];
10255                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10256                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10257                         for (j = 0;j < surface->num_vertices;j++)
10258                         {
10259                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10260                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10261                                 vi++;
10262                         }
10263                 }
10264                 R_Mesh_PrepareVertices_Generic_Unlock();
10265                 RSurf_DrawBatch();
10266         }
10267 }
10268
10269 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10270 {
10271         CHECKGLERROR
10272         RSurf_SetupDepthAndCulling();
10273         if (r_showsurfaces.integer)
10274         {
10275                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10276                 return;
10277         }
10278         switch (vid.renderpath)
10279         {
10280         case RENDERPATH_GL20:
10281         case RENDERPATH_D3D9:
10282         case RENDERPATH_D3D10:
10283         case RENDERPATH_D3D11:
10284         case RENDERPATH_SOFT:
10285         case RENDERPATH_GLES2:
10286                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10287                 break;
10288         case RENDERPATH_GL13:
10289         case RENDERPATH_GLES1:
10290                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10291                 break;
10292         case RENDERPATH_GL11:
10293                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10294                 break;
10295         }
10296         CHECKGLERROR
10297 }
10298
10299 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10300 {
10301         CHECKGLERROR
10302         RSurf_SetupDepthAndCulling();
10303         if (r_showsurfaces.integer)
10304         {
10305                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10306                 return;
10307         }
10308         switch (vid.renderpath)
10309         {
10310         case RENDERPATH_GL20:
10311         case RENDERPATH_D3D9:
10312         case RENDERPATH_D3D10:
10313         case RENDERPATH_D3D11:
10314         case RENDERPATH_SOFT:
10315         case RENDERPATH_GLES2:
10316                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10317                 break;
10318         case RENDERPATH_GL13:
10319         case RENDERPATH_GLES1:
10320                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10321                 break;
10322         case RENDERPATH_GL11:
10323                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10324                 break;
10325         }
10326         CHECKGLERROR
10327 }
10328
10329 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10330 {
10331         int i, j;
10332         int texturenumsurfaces, endsurface;
10333         texture_t *texture;
10334         const msurface_t *surface;
10335         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10336
10337         // if the model is static it doesn't matter what value we give for
10338         // wantnormals and wanttangents, so this logic uses only rules applicable
10339         // to a model, knowing that they are meaningless otherwise
10340         if (ent == r_refdef.scene.worldentity)
10341                 RSurf_ActiveWorldEntity();
10342         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10343                 RSurf_ActiveModelEntity(ent, false, false, false);
10344         else
10345         {
10346                 switch (vid.renderpath)
10347                 {
10348                 case RENDERPATH_GL20:
10349                 case RENDERPATH_D3D9:
10350                 case RENDERPATH_D3D10:
10351                 case RENDERPATH_D3D11:
10352                 case RENDERPATH_SOFT:
10353                 case RENDERPATH_GLES2:
10354                         RSurf_ActiveModelEntity(ent, true, true, false);
10355                         break;
10356                 case RENDERPATH_GL11:
10357                 case RENDERPATH_GL13:
10358                 case RENDERPATH_GLES1:
10359                         RSurf_ActiveModelEntity(ent, true, false, false);
10360                         break;
10361                 }
10362         }
10363
10364         if (r_transparentdepthmasking.integer)
10365         {
10366                 qboolean setup = false;
10367                 for (i = 0;i < numsurfaces;i = j)
10368                 {
10369                         j = i + 1;
10370                         surface = rsurface.modelsurfaces + surfacelist[i];
10371                         texture = surface->texture;
10372                         rsurface.texture = R_GetCurrentTexture(texture);
10373                         rsurface.lightmaptexture = NULL;
10374                         rsurface.deluxemaptexture = NULL;
10375                         rsurface.uselightmaptexture = false;
10376                         // scan ahead until we find a different texture
10377                         endsurface = min(i + 1024, numsurfaces);
10378                         texturenumsurfaces = 0;
10379                         texturesurfacelist[texturenumsurfaces++] = surface;
10380                         for (;j < endsurface;j++)
10381                         {
10382                                 surface = rsurface.modelsurfaces + surfacelist[j];
10383                                 if (texture != surface->texture)
10384                                         break;
10385                                 texturesurfacelist[texturenumsurfaces++] = surface;
10386                         }
10387                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10388                                 continue;
10389                         // render the range of surfaces as depth
10390                         if (!setup)
10391                         {
10392                                 setup = true;
10393                                 GL_ColorMask(0,0,0,0);
10394                                 GL_Color(1,1,1,1);
10395                                 GL_DepthTest(true);
10396                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10397                                 GL_DepthMask(true);
10398 //                              R_Mesh_ResetTextureState();
10399                                 R_SetupShader_DepthOrShadow(false, false);
10400                         }
10401                         RSurf_SetupDepthAndCulling();
10402                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10403                         if (rsurface.batchvertex3fbuffer)
10404                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10405                         else
10406                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10407                         RSurf_DrawBatch();
10408                 }
10409                 if (setup)
10410                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10411         }
10412
10413         for (i = 0;i < numsurfaces;i = j)
10414         {
10415                 j = i + 1;
10416                 surface = rsurface.modelsurfaces + surfacelist[i];
10417                 texture = surface->texture;
10418                 rsurface.texture = R_GetCurrentTexture(texture);
10419                 // scan ahead until we find a different texture
10420                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10421                 texturenumsurfaces = 0;
10422                 texturesurfacelist[texturenumsurfaces++] = surface;
10423                 if(FAKELIGHT_ENABLED)
10424                 {
10425                         rsurface.lightmaptexture = NULL;
10426                         rsurface.deluxemaptexture = NULL;
10427                         rsurface.uselightmaptexture = false;
10428                         for (;j < endsurface;j++)
10429                         {
10430                                 surface = rsurface.modelsurfaces + surfacelist[j];
10431                                 if (texture != surface->texture)
10432                                         break;
10433                                 texturesurfacelist[texturenumsurfaces++] = surface;
10434                         }
10435                 }
10436                 else
10437                 {
10438                         rsurface.lightmaptexture = surface->lightmaptexture;
10439                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10440                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10441                         for (;j < endsurface;j++)
10442                         {
10443                                 surface = rsurface.modelsurfaces + surfacelist[j];
10444                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10445                                         break;
10446                                 texturesurfacelist[texturenumsurfaces++] = surface;
10447                         }
10448                 }
10449                 // render the range of surfaces
10450                 if (ent == r_refdef.scene.worldentity)
10451                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10452                 else
10453                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10454         }
10455         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10456 }
10457
10458 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10459 {
10460         // transparent surfaces get pushed off into the transparent queue
10461         int surfacelistindex;
10462         const msurface_t *surface;
10463         vec3_t tempcenter, center;
10464         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10465         {
10466                 surface = texturesurfacelist[surfacelistindex];
10467                 if (r_transparent_sortsurfacesbynearest.integer)
10468                 {
10469                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10470                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10471                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10472                 }
10473                 else
10474                 {
10475                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10476                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10477                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10478                 }
10479                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10480                 if (rsurface.entity->transparent_offset) // transparent offset
10481                 {
10482                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10483                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10484                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10485                 }
10486                 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);
10487         }
10488 }
10489
10490 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10491 {
10492         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10493                 return;
10494         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10495                 return;
10496         RSurf_SetupDepthAndCulling();
10497         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10498         if (rsurface.batchvertex3fbuffer)
10499                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10500         else
10501                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10502         RSurf_DrawBatch();
10503 }
10504
10505 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10506 {
10507         CHECKGLERROR
10508         if (depthonly)
10509                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10510         else if (prepass)
10511         {
10512                 if (!rsurface.texture->currentnumlayers)
10513                         return;
10514                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10515                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10516                 else
10517                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10518         }
10519         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10520                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10521         else if (!rsurface.texture->currentnumlayers)
10522                 return;
10523         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10524         {
10525                 // in the deferred case, transparent surfaces were queued during prepass
10526                 if (!r_shadow_usingdeferredprepass)
10527                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10528         }
10529         else
10530         {
10531                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10532                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10533         }
10534         CHECKGLERROR
10535 }
10536
10537 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10538 {
10539         int i, j;
10540         texture_t *texture;
10541         R_FrameData_SetMark();
10542         // break the surface list down into batches by texture and use of lightmapping
10543         for (i = 0;i < numsurfaces;i = j)
10544         {
10545                 j = i + 1;
10546                 // texture is the base texture pointer, rsurface.texture is the
10547                 // current frame/skin the texture is directing us to use (for example
10548                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10549                 // use skin 1 instead)
10550                 texture = surfacelist[i]->texture;
10551                 rsurface.texture = R_GetCurrentTexture(texture);
10552                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10553                 {
10554                         // if this texture is not the kind we want, skip ahead to the next one
10555                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10556                                 ;
10557                         continue;
10558                 }
10559                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10560                 {
10561                         rsurface.lightmaptexture = NULL;
10562                         rsurface.deluxemaptexture = NULL;
10563                         rsurface.uselightmaptexture = false;
10564                         // simply scan ahead until we find a different texture or lightmap state
10565                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10566                                 ;
10567                 }
10568                 else
10569                 {
10570                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10571                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10572                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10573                         // simply scan ahead until we find a different texture or lightmap state
10574                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10575                                 ;
10576                 }
10577                 // render the range of surfaces
10578                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10579         }
10580         R_FrameData_ReturnToMark();
10581 }
10582
10583 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10584 {
10585         CHECKGLERROR
10586         if (depthonly)
10587                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10588         else if (prepass)
10589         {
10590                 if (!rsurface.texture->currentnumlayers)
10591                         return;
10592                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10593                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10594                 else
10595                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10596         }
10597         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10598                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10599         else if (!rsurface.texture->currentnumlayers)
10600                 return;
10601         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10602         {
10603                 // in the deferred case, transparent surfaces were queued during prepass
10604                 if (!r_shadow_usingdeferredprepass)
10605                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10606         }
10607         else
10608         {
10609                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10610                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10611         }
10612         CHECKGLERROR
10613 }
10614
10615 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10616 {
10617         int i, j;
10618         texture_t *texture;
10619         R_FrameData_SetMark();
10620         // break the surface list down into batches by texture and use of lightmapping
10621         for (i = 0;i < numsurfaces;i = j)
10622         {
10623                 j = i + 1;
10624                 // texture is the base texture pointer, rsurface.texture is the
10625                 // current frame/skin the texture is directing us to use (for example
10626                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10627                 // use skin 1 instead)
10628                 texture = surfacelist[i]->texture;
10629                 rsurface.texture = R_GetCurrentTexture(texture);
10630                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10631                 {
10632                         // if this texture is not the kind we want, skip ahead to the next one
10633                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10634                                 ;
10635                         continue;
10636                 }
10637                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10638                 {
10639                         rsurface.lightmaptexture = NULL;
10640                         rsurface.deluxemaptexture = NULL;
10641                         rsurface.uselightmaptexture = false;
10642                         // simply scan ahead until we find a different texture or lightmap state
10643                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10644                                 ;
10645                 }
10646                 else
10647                 {
10648                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10649                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10650                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10651                         // simply scan ahead until we find a different texture or lightmap state
10652                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10653                                 ;
10654                 }
10655                 // render the range of surfaces
10656                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10657         }
10658         R_FrameData_ReturnToMark();
10659 }
10660
10661 float locboxvertex3f[6*4*3] =
10662 {
10663         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10664         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10665         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10666         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10667         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10668         1,0,0, 0,0,0, 0,1,0, 1,1,0
10669 };
10670
10671 unsigned short locboxelements[6*2*3] =
10672 {
10673          0, 1, 2, 0, 2, 3,
10674          4, 5, 6, 4, 6, 7,
10675          8, 9,10, 8,10,11,
10676         12,13,14, 12,14,15,
10677         16,17,18, 16,18,19,
10678         20,21,22, 20,22,23
10679 };
10680
10681 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10682 {
10683         int i, j;
10684         cl_locnode_t *loc = (cl_locnode_t *)ent;
10685         vec3_t mins, size;
10686         float vertex3f[6*4*3];
10687         CHECKGLERROR
10688         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10689         GL_DepthMask(false);
10690         GL_DepthRange(0, 1);
10691         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10692         GL_DepthTest(true);
10693         GL_CullFace(GL_NONE);
10694         R_EntityMatrix(&identitymatrix);
10695
10696 //      R_Mesh_ResetTextureState();
10697
10698         i = surfacelist[0];
10699         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10700                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10701                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10702                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10703
10704         if (VectorCompare(loc->mins, loc->maxs))
10705         {
10706                 VectorSet(size, 2, 2, 2);
10707                 VectorMA(loc->mins, -0.5f, size, mins);
10708         }
10709         else
10710         {
10711                 VectorCopy(loc->mins, mins);
10712                 VectorSubtract(loc->maxs, loc->mins, size);
10713         }
10714
10715         for (i = 0;i < 6*4*3;)
10716                 for (j = 0;j < 3;j++, i++)
10717                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10718
10719         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10720         R_SetupShader_Generic_NoTexture(false, false);
10721         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10722 }
10723
10724 void R_DrawLocs(void)
10725 {
10726         int index;
10727         cl_locnode_t *loc, *nearestloc;
10728         vec3_t center;
10729         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10730         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10731         {
10732                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10733                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10734         }
10735 }
10736
10737 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10738 {
10739         if (decalsystem->decals)
10740                 Mem_Free(decalsystem->decals);
10741         memset(decalsystem, 0, sizeof(*decalsystem));
10742 }
10743
10744 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)
10745 {
10746         tridecal_t *decal;
10747         tridecal_t *decals;
10748         int i;
10749
10750         // expand or initialize the system
10751         if (decalsystem->maxdecals <= decalsystem->numdecals)
10752         {
10753                 decalsystem_t old = *decalsystem;
10754                 qboolean useshortelements;
10755                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10756                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10757                 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)));
10758                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10759                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10760                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10761                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10762                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10763                 if (decalsystem->numdecals)
10764                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10765                 if (old.decals)
10766                         Mem_Free(old.decals);
10767                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10768                         decalsystem->element3i[i] = i;
10769                 if (useshortelements)
10770                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10771                                 decalsystem->element3s[i] = i;
10772         }
10773
10774         // grab a decal and search for another free slot for the next one
10775         decals = decalsystem->decals;
10776         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10777         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10778                 ;
10779         decalsystem->freedecal = i;
10780         if (decalsystem->numdecals <= i)
10781                 decalsystem->numdecals = i + 1;
10782
10783         // initialize the decal
10784         decal->lived = 0;
10785         decal->triangleindex = triangleindex;
10786         decal->surfaceindex = surfaceindex;
10787         decal->decalsequence = decalsequence;
10788         decal->color4f[0][0] = c0[0];
10789         decal->color4f[0][1] = c0[1];
10790         decal->color4f[0][2] = c0[2];
10791         decal->color4f[0][3] = 1;
10792         decal->color4f[1][0] = c1[0];
10793         decal->color4f[1][1] = c1[1];
10794         decal->color4f[1][2] = c1[2];
10795         decal->color4f[1][3] = 1;
10796         decal->color4f[2][0] = c2[0];
10797         decal->color4f[2][1] = c2[1];
10798         decal->color4f[2][2] = c2[2];
10799         decal->color4f[2][3] = 1;
10800         decal->vertex3f[0][0] = v0[0];
10801         decal->vertex3f[0][1] = v0[1];
10802         decal->vertex3f[0][2] = v0[2];
10803         decal->vertex3f[1][0] = v1[0];
10804         decal->vertex3f[1][1] = v1[1];
10805         decal->vertex3f[1][2] = v1[2];
10806         decal->vertex3f[2][0] = v2[0];
10807         decal->vertex3f[2][1] = v2[1];
10808         decal->vertex3f[2][2] = v2[2];
10809         decal->texcoord2f[0][0] = t0[0];
10810         decal->texcoord2f[0][1] = t0[1];
10811         decal->texcoord2f[1][0] = t1[0];
10812         decal->texcoord2f[1][1] = t1[1];
10813         decal->texcoord2f[2][0] = t2[0];
10814         decal->texcoord2f[2][1] = t2[1];
10815         TriangleNormal(v0, v1, v2, decal->plane);
10816         VectorNormalize(decal->plane);
10817         decal->plane[3] = DotProduct(v0, decal->plane);
10818 }
10819
10820 extern cvar_t cl_decals_bias;
10821 extern cvar_t cl_decals_models;
10822 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10823 // baseparms, parms, temps
10824 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)
10825 {
10826         int cornerindex;
10827         int index;
10828         float v[9][3];
10829         const float *vertex3f;
10830         const float *normal3f;
10831         int numpoints;
10832         float points[2][9][3];
10833         float temp[3];
10834         float tc[9][2];
10835         float f;
10836         float c[9][4];
10837         const int *e;
10838
10839         e = rsurface.modelelement3i + 3*triangleindex;
10840
10841         vertex3f = rsurface.modelvertex3f;
10842         normal3f = rsurface.modelnormal3f;
10843
10844         if (normal3f)
10845         {
10846                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10847                 {
10848                         index = 3*e[cornerindex];
10849                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10850                 }
10851         }
10852         else
10853         {
10854                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10855                 {
10856                         index = 3*e[cornerindex];
10857                         VectorCopy(vertex3f + index, v[cornerindex]);
10858                 }
10859         }
10860
10861         // cull backfaces
10862         //TriangleNormal(v[0], v[1], v[2], normal);
10863         //if (DotProduct(normal, localnormal) < 0.0f)
10864         //      continue;
10865         // clip by each of the box planes formed from the projection matrix
10866         // if anything survives, we emit the decal
10867         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]);
10868         if (numpoints < 3)
10869                 return;
10870         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]);
10871         if (numpoints < 3)
10872                 return;
10873         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]);
10874         if (numpoints < 3)
10875                 return;
10876         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]);
10877         if (numpoints < 3)
10878                 return;
10879         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]);
10880         if (numpoints < 3)
10881                 return;
10882         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]);
10883         if (numpoints < 3)
10884                 return;
10885         // some part of the triangle survived, so we have to accept it...
10886         if (dynamic)
10887         {
10888                 // dynamic always uses the original triangle
10889                 numpoints = 3;
10890                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10891                 {
10892                         index = 3*e[cornerindex];
10893                         VectorCopy(vertex3f + index, v[cornerindex]);
10894                 }
10895         }
10896         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10897         {
10898                 // convert vertex positions to texcoords
10899                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10900                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10901                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10902                 // calculate distance fade from the projection origin
10903                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10904                 f = bound(0.0f, f, 1.0f);
10905                 c[cornerindex][0] = r * f;
10906                 c[cornerindex][1] = g * f;
10907                 c[cornerindex][2] = b * f;
10908                 c[cornerindex][3] = 1.0f;
10909                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10910         }
10911         if (dynamic)
10912                 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);
10913         else
10914                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10915                         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);
10916 }
10917 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)
10918 {
10919         matrix4x4_t projection;
10920         decalsystem_t *decalsystem;
10921         qboolean dynamic;
10922         dp_model_t *model;
10923         const msurface_t *surface;
10924         const msurface_t *surfaces;
10925         const int *surfacelist;
10926         const texture_t *texture;
10927         int numtriangles;
10928         int numsurfacelist;
10929         int surfacelistindex;
10930         int surfaceindex;
10931         int triangleindex;
10932         float localorigin[3];
10933         float localnormal[3];
10934         float localmins[3];
10935         float localmaxs[3];
10936         float localsize;
10937         //float normal[3];
10938         float planes[6][4];
10939         float angles[3];
10940         bih_t *bih;
10941         int bih_triangles_count;
10942         int bih_triangles[256];
10943         int bih_surfaces[256];
10944
10945         decalsystem = &ent->decalsystem;
10946         model = ent->model;
10947         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10948         {
10949                 R_DecalSystem_Reset(&ent->decalsystem);
10950                 return;
10951         }
10952
10953         if (!model->brush.data_leafs && !cl_decals_models.integer)
10954         {
10955                 if (decalsystem->model)
10956                         R_DecalSystem_Reset(decalsystem);
10957                 return;
10958         }
10959
10960         if (decalsystem->model != model)
10961                 R_DecalSystem_Reset(decalsystem);
10962         decalsystem->model = model;
10963
10964         RSurf_ActiveModelEntity(ent, true, false, false);
10965
10966         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10967         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10968         VectorNormalize(localnormal);
10969         localsize = worldsize*rsurface.inversematrixscale;
10970         localmins[0] = localorigin[0] - localsize;
10971         localmins[1] = localorigin[1] - localsize;
10972         localmins[2] = localorigin[2] - localsize;
10973         localmaxs[0] = localorigin[0] + localsize;
10974         localmaxs[1] = localorigin[1] + localsize;
10975         localmaxs[2] = localorigin[2] + localsize;
10976
10977         //VectorCopy(localnormal, planes[4]);
10978         //VectorVectors(planes[4], planes[2], planes[0]);
10979         AnglesFromVectors(angles, localnormal, NULL, false);
10980         AngleVectors(angles, planes[0], planes[2], planes[4]);
10981         VectorNegate(planes[0], planes[1]);
10982         VectorNegate(planes[2], planes[3]);
10983         VectorNegate(planes[4], planes[5]);
10984         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10985         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10986         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10987         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10988         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10989         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10990
10991 #if 1
10992 // works
10993 {
10994         matrix4x4_t forwardprojection;
10995         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10996         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10997 }
10998 #else
10999 // broken
11000 {
11001         float projectionvector[4][3];
11002         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11003         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11004         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11005         projectionvector[0][0] = planes[0][0] * ilocalsize;
11006         projectionvector[0][1] = planes[1][0] * ilocalsize;
11007         projectionvector[0][2] = planes[2][0] * ilocalsize;
11008         projectionvector[1][0] = planes[0][1] * ilocalsize;
11009         projectionvector[1][1] = planes[1][1] * ilocalsize;
11010         projectionvector[1][2] = planes[2][1] * ilocalsize;
11011         projectionvector[2][0] = planes[0][2] * ilocalsize;
11012         projectionvector[2][1] = planes[1][2] * ilocalsize;
11013         projectionvector[2][2] = planes[2][2] * ilocalsize;
11014         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11015         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11016         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11017         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11018 }
11019 #endif
11020
11021         dynamic = model->surfmesh.isanimated;
11022         numsurfacelist = model->nummodelsurfaces;
11023         surfacelist = model->sortedmodelsurfaces;
11024         surfaces = model->data_surfaces;
11025
11026         bih = NULL;
11027         bih_triangles_count = -1;
11028         if(!dynamic)
11029         {
11030                 if(model->render_bih.numleafs)
11031                         bih = &model->render_bih;
11032                 else if(model->collision_bih.numleafs)
11033                         bih = &model->collision_bih;
11034         }
11035         if(bih)
11036                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11037         if(bih_triangles_count == 0)
11038                 return;
11039         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11040                 return;
11041         if(bih_triangles_count > 0)
11042         {
11043                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11044                 {
11045                         surfaceindex = bih_surfaces[triangleindex];
11046                         surface = surfaces + surfaceindex;
11047                         texture = surface->texture;
11048                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11049                                 continue;
11050                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11051                                 continue;
11052                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11053                 }
11054         }
11055         else
11056         {
11057                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11058                 {
11059                         surfaceindex = surfacelist[surfacelistindex];
11060                         surface = surfaces + surfaceindex;
11061                         // check cull box first because it rejects more than any other check
11062                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11063                                 continue;
11064                         // skip transparent surfaces
11065                         texture = surface->texture;
11066                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11067                                 continue;
11068                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11069                                 continue;
11070                         numtriangles = surface->num_triangles;
11071                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11072                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11073                 }
11074         }
11075 }
11076
11077 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11078 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)
11079 {
11080         int renderentityindex;
11081         float worldmins[3];
11082         float worldmaxs[3];
11083         entity_render_t *ent;
11084
11085         if (!cl_decals_newsystem.integer)
11086                 return;
11087
11088         worldmins[0] = worldorigin[0] - worldsize;
11089         worldmins[1] = worldorigin[1] - worldsize;
11090         worldmins[2] = worldorigin[2] - worldsize;
11091         worldmaxs[0] = worldorigin[0] + worldsize;
11092         worldmaxs[1] = worldorigin[1] + worldsize;
11093         worldmaxs[2] = worldorigin[2] + worldsize;
11094
11095         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11096
11097         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11098         {
11099                 ent = r_refdef.scene.entities[renderentityindex];
11100                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11101                         continue;
11102
11103                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11104         }
11105 }
11106
11107 typedef struct r_decalsystem_splatqueue_s
11108 {
11109         vec3_t worldorigin;
11110         vec3_t worldnormal;
11111         float color[4];
11112         float tcrange[4];
11113         float worldsize;
11114         int decalsequence;
11115 }
11116 r_decalsystem_splatqueue_t;
11117
11118 int r_decalsystem_numqueued = 0;
11119 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11120
11121 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)
11122 {
11123         r_decalsystem_splatqueue_t *queue;
11124
11125         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11126                 return;
11127
11128         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11129         VectorCopy(worldorigin, queue->worldorigin);
11130         VectorCopy(worldnormal, queue->worldnormal);
11131         Vector4Set(queue->color, r, g, b, a);
11132         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11133         queue->worldsize = worldsize;
11134         queue->decalsequence = cl.decalsequence++;
11135 }
11136
11137 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11138 {
11139         int i;
11140         r_decalsystem_splatqueue_t *queue;
11141
11142         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11143                 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);
11144         r_decalsystem_numqueued = 0;
11145 }
11146
11147 extern cvar_t cl_decals_max;
11148 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11149 {
11150         int i;
11151         decalsystem_t *decalsystem = &ent->decalsystem;
11152         int numdecals;
11153         int killsequence;
11154         tridecal_t *decal;
11155         float frametime;
11156         float lifetime;
11157
11158         if (!decalsystem->numdecals)
11159                 return;
11160
11161         if (r_showsurfaces.integer)
11162                 return;
11163
11164         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11165         {
11166                 R_DecalSystem_Reset(decalsystem);
11167                 return;
11168         }
11169
11170         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11171         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11172
11173         if (decalsystem->lastupdatetime)
11174                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11175         else
11176                 frametime = 0;
11177         decalsystem->lastupdatetime = r_refdef.scene.time;
11178         decal = decalsystem->decals;
11179         numdecals = decalsystem->numdecals;
11180
11181         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11182         {
11183                 if (decal->color4f[0][3])
11184                 {
11185                         decal->lived += frametime;
11186                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11187                         {
11188                                 memset(decal, 0, sizeof(*decal));
11189                                 if (decalsystem->freedecal > i)
11190                                         decalsystem->freedecal = i;
11191                         }
11192                 }
11193         }
11194         decal = decalsystem->decals;
11195         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11196                 numdecals--;
11197
11198         // collapse the array by shuffling the tail decals into the gaps
11199         for (;;)
11200         {
11201                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11202                         decalsystem->freedecal++;
11203                 if (decalsystem->freedecal == numdecals)
11204                         break;
11205                 decal[decalsystem->freedecal] = decal[--numdecals];
11206         }
11207
11208         decalsystem->numdecals = numdecals;
11209
11210         if (numdecals <= 0)
11211         {
11212                 // if there are no decals left, reset decalsystem
11213                 R_DecalSystem_Reset(decalsystem);
11214         }
11215 }
11216
11217 extern skinframe_t *decalskinframe;
11218 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11219 {
11220         int i;
11221         decalsystem_t *decalsystem = &ent->decalsystem;
11222         int numdecals;
11223         tridecal_t *decal;
11224         float faderate;
11225         float alpha;
11226         float *v3f;
11227         float *c4f;
11228         float *t2f;
11229         const int *e;
11230         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11231         int numtris = 0;
11232
11233         numdecals = decalsystem->numdecals;
11234         if (!numdecals)
11235                 return;
11236
11237         if (r_showsurfaces.integer)
11238                 return;
11239
11240         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11241         {
11242                 R_DecalSystem_Reset(decalsystem);
11243                 return;
11244         }
11245
11246         // if the model is static it doesn't matter what value we give for
11247         // wantnormals and wanttangents, so this logic uses only rules applicable
11248         // to a model, knowing that they are meaningless otherwise
11249         if (ent == r_refdef.scene.worldentity)
11250                 RSurf_ActiveWorldEntity();
11251         else
11252                 RSurf_ActiveModelEntity(ent, false, false, false);
11253
11254         decalsystem->lastupdatetime = r_refdef.scene.time;
11255         decal = decalsystem->decals;
11256
11257         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11258
11259         // update vertex positions for animated models
11260         v3f = decalsystem->vertex3f;
11261         c4f = decalsystem->color4f;
11262         t2f = decalsystem->texcoord2f;
11263         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11264         {
11265                 if (!decal->color4f[0][3])
11266                         continue;
11267
11268                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11269                         continue;
11270
11271                 // skip backfaces
11272                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11273                         continue;
11274
11275                 // update color values for fading decals
11276                 if (decal->lived >= cl_decals_time.value)
11277                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11278                 else
11279                         alpha = 1.0f;
11280
11281                 c4f[ 0] = decal->color4f[0][0] * alpha;
11282                 c4f[ 1] = decal->color4f[0][1] * alpha;
11283                 c4f[ 2] = decal->color4f[0][2] * alpha;
11284                 c4f[ 3] = 1;
11285                 c4f[ 4] = decal->color4f[1][0] * alpha;
11286                 c4f[ 5] = decal->color4f[1][1] * alpha;
11287                 c4f[ 6] = decal->color4f[1][2] * alpha;
11288                 c4f[ 7] = 1;
11289                 c4f[ 8] = decal->color4f[2][0] * alpha;
11290                 c4f[ 9] = decal->color4f[2][1] * alpha;
11291                 c4f[10] = decal->color4f[2][2] * alpha;
11292                 c4f[11] = 1;
11293
11294                 t2f[0] = decal->texcoord2f[0][0];
11295                 t2f[1] = decal->texcoord2f[0][1];
11296                 t2f[2] = decal->texcoord2f[1][0];
11297                 t2f[3] = decal->texcoord2f[1][1];
11298                 t2f[4] = decal->texcoord2f[2][0];
11299                 t2f[5] = decal->texcoord2f[2][1];
11300
11301                 // update vertex positions for animated models
11302                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11303                 {
11304                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11305                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11306                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11307                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11308                 }
11309                 else
11310                 {
11311                         VectorCopy(decal->vertex3f[0], v3f);
11312                         VectorCopy(decal->vertex3f[1], v3f + 3);
11313                         VectorCopy(decal->vertex3f[2], v3f + 6);
11314                 }
11315
11316                 if (r_refdef.fogenabled)
11317                 {
11318                         alpha = RSurf_FogVertex(v3f);
11319                         VectorScale(c4f, alpha, c4f);
11320                         alpha = RSurf_FogVertex(v3f + 3);
11321                         VectorScale(c4f + 4, alpha, c4f + 4);
11322                         alpha = RSurf_FogVertex(v3f + 6);
11323                         VectorScale(c4f + 8, alpha, c4f + 8);
11324                 }
11325
11326                 v3f += 9;
11327                 c4f += 12;
11328                 t2f += 6;
11329                 numtris++;
11330         }
11331
11332         if (numtris > 0)
11333         {
11334                 r_refdef.stats.drawndecals += numtris;
11335
11336                 // now render the decals all at once
11337                 // (this assumes they all use one particle font texture!)
11338                 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);
11339 //              R_Mesh_ResetTextureState();
11340                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11341                 GL_DepthMask(false);
11342                 GL_DepthRange(0, 1);
11343                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11344                 GL_DepthTest(true);
11345                 GL_CullFace(GL_NONE);
11346                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11347                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11348                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11349         }
11350 }
11351
11352 static void R_DrawModelDecals(void)
11353 {
11354         int i, numdecals;
11355
11356         // fade faster when there are too many decals
11357         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11358         for (i = 0;i < r_refdef.scene.numentities;i++)
11359                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11360
11361         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11362         for (i = 0;i < r_refdef.scene.numentities;i++)
11363                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11364                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11365
11366         R_DecalSystem_ApplySplatEntitiesQueue();
11367
11368         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11369         for (i = 0;i < r_refdef.scene.numentities;i++)
11370                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11371
11372         r_refdef.stats.totaldecals += numdecals;
11373
11374         if (r_showsurfaces.integer)
11375                 return;
11376
11377         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11378
11379         for (i = 0;i < r_refdef.scene.numentities;i++)
11380         {
11381                 if (!r_refdef.viewcache.entityvisible[i])
11382                         continue;
11383                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11384                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11385         }
11386 }
11387
11388 extern cvar_t mod_collision_bih;
11389 static void R_DrawDebugModel(void)
11390 {
11391         entity_render_t *ent = rsurface.entity;
11392         int i, j, k, l, flagsmask;
11393         const msurface_t *surface;
11394         dp_model_t *model = ent->model;
11395         vec3_t v;
11396
11397         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11398                 return;
11399
11400         if (r_showoverdraw.value > 0)
11401         {
11402                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11403                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11404                 R_SetupShader_Generic_NoTexture(false, false);
11405                 GL_DepthTest(false);
11406                 GL_DepthMask(false);
11407                 GL_DepthRange(0, 1);
11408                 GL_BlendFunc(GL_ONE, GL_ONE);
11409                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11410                 {
11411                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11412                                 continue;
11413                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11414                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11415                         {
11416                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11417                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11418                                 if (!rsurface.texture->currentlayers->depthmask)
11419                                         GL_Color(c, 0, 0, 1.0f);
11420                                 else if (ent == r_refdef.scene.worldentity)
11421                                         GL_Color(c, c, c, 1.0f);
11422                                 else
11423                                         GL_Color(0, c, 0, 1.0f);
11424                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11425                                 RSurf_DrawBatch();
11426                         }
11427                 }
11428                 rsurface.texture = NULL;
11429         }
11430
11431         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11432
11433 //      R_Mesh_ResetTextureState();
11434         R_SetupShader_Generic_NoTexture(false, false);
11435         GL_DepthRange(0, 1);
11436         GL_DepthTest(!r_showdisabledepthtest.integer);
11437         GL_DepthMask(false);
11438         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11439
11440         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11441         {
11442                 int triangleindex;
11443                 int bihleafindex;
11444                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11445                 const q3mbrush_t *brush;
11446                 const bih_t *bih = &model->collision_bih;
11447                 const bih_leaf_t *bihleaf;
11448                 float vertex3f[3][3];
11449                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11450                 cullbox = false;
11451                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11452                 {
11453                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11454                                 continue;
11455                         switch (bihleaf->type)
11456                         {
11457                         case BIH_BRUSH:
11458                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11459                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11460                                 {
11461                                         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);
11462                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11463                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11464                                 }
11465                                 break;
11466                         case BIH_COLLISIONTRIANGLE:
11467                                 triangleindex = bihleaf->itemindex;
11468                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11469                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11470                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11471                                 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);
11472                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11473                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11474                                 break;
11475                         case BIH_RENDERTRIANGLE:
11476                                 triangleindex = bihleaf->itemindex;
11477                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11478                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11479                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11480                                 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);
11481                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11482                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11483                                 break;
11484                         }
11485                 }
11486         }
11487
11488         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11489
11490 #ifndef USE_GLES2
11491         if (r_showtris.integer && qglPolygonMode)
11492         {
11493                 if (r_showdisabledepthtest.integer)
11494                 {
11495                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11496                         GL_DepthMask(false);
11497                 }
11498                 else
11499                 {
11500                         GL_BlendFunc(GL_ONE, GL_ZERO);
11501                         GL_DepthMask(true);
11502                 }
11503                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11504                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11505                 {
11506                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11507                                 continue;
11508                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11509                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11510                         {
11511                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11512                                 if (!rsurface.texture->currentlayers->depthmask)
11513                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11514                                 else if (ent == r_refdef.scene.worldentity)
11515                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11516                                 else
11517                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11518                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11519                                 RSurf_DrawBatch();
11520                         }
11521                 }
11522                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11523                 rsurface.texture = NULL;
11524         }
11525
11526         if (r_shownormals.value != 0 && qglBegin)
11527         {
11528                 if (r_showdisabledepthtest.integer)
11529                 {
11530                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11531                         GL_DepthMask(false);
11532                 }
11533                 else
11534                 {
11535                         GL_BlendFunc(GL_ONE, GL_ZERO);
11536                         GL_DepthMask(true);
11537                 }
11538                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11539                 {
11540                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11541                                 continue;
11542                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11543                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11544                         {
11545                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11546                                 qglBegin(GL_LINES);
11547                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11548                                 {
11549                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11550                                         {
11551                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11552                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11553                                                 qglVertex3f(v[0], v[1], v[2]);
11554                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11555                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11556                                                 qglVertex3f(v[0], v[1], v[2]);
11557                                         }
11558                                 }
11559                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11560                                 {
11561                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11562                                         {
11563                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11564                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11565                                                 qglVertex3f(v[0], v[1], v[2]);
11566                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11567                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11568                                                 qglVertex3f(v[0], v[1], v[2]);
11569                                         }
11570                                 }
11571                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11572                                 {
11573                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11574                                         {
11575                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11576                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11577                                                 qglVertex3f(v[0], v[1], v[2]);
11578                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11579                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11580                                                 qglVertex3f(v[0], v[1], v[2]);
11581                                         }
11582                                 }
11583                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11584                                 {
11585                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11586                                         {
11587                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11588                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11589                                                 qglVertex3f(v[0], v[1], v[2]);
11590                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11591                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11592                                                 qglVertex3f(v[0], v[1], v[2]);
11593                                         }
11594                                 }
11595                                 qglEnd();
11596                                 CHECKGLERROR
11597                         }
11598                 }
11599                 rsurface.texture = NULL;
11600         }
11601 #endif
11602 }
11603
11604 int r_maxsurfacelist = 0;
11605 const msurface_t **r_surfacelist = NULL;
11606 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11607 {
11608         int i, j, endj, flagsmask;
11609         dp_model_t *model = r_refdef.scene.worldmodel;
11610         msurface_t *surfaces;
11611         unsigned char *update;
11612         int numsurfacelist = 0;
11613         if (model == NULL)
11614                 return;
11615
11616         if (r_maxsurfacelist < model->num_surfaces)
11617         {
11618                 r_maxsurfacelist = model->num_surfaces;
11619                 if (r_surfacelist)
11620                         Mem_Free((msurface_t**)r_surfacelist);
11621                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11622         }
11623
11624         RSurf_ActiveWorldEntity();
11625
11626         surfaces = model->data_surfaces;
11627         update = model->brushq1.lightmapupdateflags;
11628
11629         // update light styles on this submodel
11630         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11631         {
11632                 model_brush_lightstyleinfo_t *style;
11633                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11634                 {
11635                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11636                         {
11637                                 int *list = style->surfacelist;
11638                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11639                                 for (j = 0;j < style->numsurfaces;j++)
11640                                         update[list[j]] = true;
11641                         }
11642                 }
11643         }
11644
11645         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11646
11647         if (debug)
11648         {
11649                 R_DrawDebugModel();
11650                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11651                 return;
11652         }
11653
11654         rsurface.lightmaptexture = NULL;
11655         rsurface.deluxemaptexture = NULL;
11656         rsurface.uselightmaptexture = false;
11657         rsurface.texture = NULL;
11658         rsurface.rtlight = NULL;
11659         numsurfacelist = 0;
11660         // add visible surfaces to draw list
11661         for (i = 0;i < model->nummodelsurfaces;i++)
11662         {
11663                 j = model->sortedmodelsurfaces[i];
11664                 if (r_refdef.viewcache.world_surfacevisible[j])
11665                         r_surfacelist[numsurfacelist++] = surfaces + j;
11666         }
11667         // update lightmaps if needed
11668         if (model->brushq1.firstrender)
11669         {
11670                 model->brushq1.firstrender = false;
11671                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11672                         if (update[j])
11673                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11674         }
11675         else if (update)
11676         {
11677                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11678                         if (r_refdef.viewcache.world_surfacevisible[j])
11679                                 if (update[j])
11680                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11681         }
11682         // don't do anything if there were no surfaces
11683         if (!numsurfacelist)
11684         {
11685                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11686                 return;
11687         }
11688         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11689
11690         // add to stats if desired
11691         if (r_speeds.integer && !skysurfaces && !depthonly)
11692         {
11693                 r_refdef.stats.world_surfaces += numsurfacelist;
11694                 for (j = 0;j < numsurfacelist;j++)
11695                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11696         }
11697
11698         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11699 }
11700
11701 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11702 {
11703         int i, j, endj, flagsmask;
11704         dp_model_t *model = ent->model;
11705         msurface_t *surfaces;
11706         unsigned char *update;
11707         int numsurfacelist = 0;
11708         if (model == NULL)
11709                 return;
11710
11711         if (r_maxsurfacelist < model->num_surfaces)
11712         {
11713                 r_maxsurfacelist = model->num_surfaces;
11714                 if (r_surfacelist)
11715                         Mem_Free((msurface_t **)r_surfacelist);
11716                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11717         }
11718
11719         // if the model is static it doesn't matter what value we give for
11720         // wantnormals and wanttangents, so this logic uses only rules applicable
11721         // to a model, knowing that they are meaningless otherwise
11722         if (ent == r_refdef.scene.worldentity)
11723                 RSurf_ActiveWorldEntity();
11724         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11725                 RSurf_ActiveModelEntity(ent, false, false, false);
11726         else if (prepass)
11727                 RSurf_ActiveModelEntity(ent, true, true, true);
11728         else if (depthonly)
11729         {
11730                 switch (vid.renderpath)
11731                 {
11732                 case RENDERPATH_GL20:
11733                 case RENDERPATH_D3D9:
11734                 case RENDERPATH_D3D10:
11735                 case RENDERPATH_D3D11:
11736                 case RENDERPATH_SOFT:
11737                 case RENDERPATH_GLES2:
11738                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11739                         break;
11740                 case RENDERPATH_GL11:
11741                 case RENDERPATH_GL13:
11742                 case RENDERPATH_GLES1:
11743                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11744                         break;
11745                 }
11746         }
11747         else
11748         {
11749                 switch (vid.renderpath)
11750                 {
11751                 case RENDERPATH_GL20:
11752                 case RENDERPATH_D3D9:
11753                 case RENDERPATH_D3D10:
11754                 case RENDERPATH_D3D11:
11755                 case RENDERPATH_SOFT:
11756                 case RENDERPATH_GLES2:
11757                         RSurf_ActiveModelEntity(ent, true, true, false);
11758                         break;
11759                 case RENDERPATH_GL11:
11760                 case RENDERPATH_GL13:
11761                 case RENDERPATH_GLES1:
11762                         RSurf_ActiveModelEntity(ent, true, false, false);
11763                         break;
11764                 }
11765         }
11766
11767         surfaces = model->data_surfaces;
11768         update = model->brushq1.lightmapupdateflags;
11769
11770         // update light styles
11771         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11772         {
11773                 model_brush_lightstyleinfo_t *style;
11774                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11775                 {
11776                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11777                         {
11778                                 int *list = style->surfacelist;
11779                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11780                                 for (j = 0;j < style->numsurfaces;j++)
11781                                         update[list[j]] = true;
11782                         }
11783                 }
11784         }
11785
11786         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11787
11788         if (debug)
11789         {
11790                 R_DrawDebugModel();
11791                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11792                 return;
11793         }
11794
11795         rsurface.lightmaptexture = NULL;
11796         rsurface.deluxemaptexture = NULL;
11797         rsurface.uselightmaptexture = false;
11798         rsurface.texture = NULL;
11799         rsurface.rtlight = NULL;
11800         numsurfacelist = 0;
11801         // add visible surfaces to draw list
11802         for (i = 0;i < model->nummodelsurfaces;i++)
11803                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11804         // don't do anything if there were no surfaces
11805         if (!numsurfacelist)
11806         {
11807                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11808                 return;
11809         }
11810         // update lightmaps if needed
11811         if (update)
11812         {
11813                 int updated = 0;
11814                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11815                 {
11816                         if (update[j])
11817                         {
11818                                 updated++;
11819                                 R_BuildLightMap(ent, surfaces + j);
11820                         }
11821                 }
11822         }
11823         if (update)
11824                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11825                         if (update[j])
11826                                 R_BuildLightMap(ent, surfaces + j);
11827         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11828
11829         // add to stats if desired
11830         if (r_speeds.integer && !skysurfaces && !depthonly)
11831         {
11832                 r_refdef.stats.entities_surfaces += numsurfacelist;
11833                 for (j = 0;j < numsurfacelist;j++)
11834                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11835         }
11836
11837         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11838 }
11839
11840 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11841 {
11842         static texture_t texture;
11843         static msurface_t surface;
11844         const msurface_t *surfacelist = &surface;
11845
11846         // fake enough texture and surface state to render this geometry
11847
11848         texture.update_lastrenderframe = -1; // regenerate this texture
11849         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11850         texture.currentskinframe = skinframe;
11851         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11852         texture.offsetmapping = OFFSETMAPPING_OFF;
11853         texture.offsetscale = 1;
11854         texture.specularscalemod = 1;
11855         texture.specularpowermod = 1;
11856
11857         surface.texture = &texture;
11858         surface.num_triangles = numtriangles;
11859         surface.num_firsttriangle = firsttriangle;
11860         surface.num_vertices = numvertices;
11861         surface.num_firstvertex = firstvertex;
11862
11863         // now render it
11864         rsurface.texture = R_GetCurrentTexture(surface.texture);
11865         rsurface.lightmaptexture = NULL;
11866         rsurface.deluxemaptexture = NULL;
11867         rsurface.uselightmaptexture = false;
11868         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11869 }
11870
11871 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)
11872 {
11873         static msurface_t surface;
11874         const msurface_t *surfacelist = &surface;
11875
11876         // fake enough texture and surface state to render this geometry
11877         surface.texture = texture;
11878         surface.num_triangles = numtriangles;
11879         surface.num_firsttriangle = firsttriangle;
11880         surface.num_vertices = numvertices;
11881         surface.num_firstvertex = firstvertex;
11882
11883         // now render it
11884         rsurface.texture = R_GetCurrentTexture(surface.texture);
11885         rsurface.lightmaptexture = NULL;
11886         rsurface.deluxemaptexture = NULL;
11887         rsurface.uselightmaptexture = false;
11888         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11889 }