]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
002355ccdd64882000d45a1eb7f3841b7c37f014
[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 - NOTE: bad performance on multi-gpu!"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
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 (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
136 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
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 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
207
208 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
209 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
210 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
211 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
212 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
213 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
214 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
215 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
216 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
217 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
218
219 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"};
220
221 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"};
222
223 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
224
225 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
226
227 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
228 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"};
229
230 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, requires mod_q3shader_force_terrain_alphaflag on."};
231
232 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)"};
233
234 extern cvar_t v_glslgamma;
235 extern cvar_t v_glslgamma_2d;
236
237 extern qboolean v_flipped_state;
238
239 r_framebufferstate_t r_fb;
240
241 /// shadow volume bsp struct with automatically growing nodes buffer
242 svbsp_t r_svbsp;
243
244 rtexture_t *r_texture_blanknormalmap;
245 rtexture_t *r_texture_white;
246 rtexture_t *r_texture_grey128;
247 rtexture_t *r_texture_black;
248 rtexture_t *r_texture_notexture;
249 rtexture_t *r_texture_whitecube;
250 rtexture_t *r_texture_normalizationcube;
251 rtexture_t *r_texture_fogattenuation;
252 rtexture_t *r_texture_fogheighttexture;
253 rtexture_t *r_texture_gammaramps;
254 unsigned int r_texture_gammaramps_serial;
255 //rtexture_t *r_texture_fogintensity;
256 rtexture_t *r_texture_reflectcube;
257
258 // TODO: hash lookups?
259 typedef struct cubemapinfo_s
260 {
261         char basename[64];
262         rtexture_t *texture;
263 }
264 cubemapinfo_t;
265
266 int r_texture_numcubemaps;
267 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
268
269 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
270 unsigned int r_numqueries;
271 unsigned int r_maxqueries;
272
273 typedef struct r_qwskincache_s
274 {
275         char name[MAX_QPATH];
276         skinframe_t *skinframe;
277 }
278 r_qwskincache_t;
279
280 static r_qwskincache_t *r_qwskincache;
281 static int r_qwskincache_size;
282
283 /// vertex coordinates for a quad that covers the screen exactly
284 extern const float r_screenvertex3f[12];
285 extern const float r_d3dscreenvertex3f[12];
286 const float r_screenvertex3f[12] =
287 {
288         0, 0, 0,
289         1, 0, 0,
290         1, 1, 0,
291         0, 1, 0
292 };
293 const float r_d3dscreenvertex3f[12] =
294 {
295         0, 1, 0,
296         1, 1, 0,
297         1, 0, 0,
298         0, 0, 0
299 };
300
301 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
302 {
303         int i;
304         for (i = 0;i < verts;i++)
305         {
306                 out[0] = in[0] * r;
307                 out[1] = in[1] * g;
308                 out[2] = in[2] * b;
309                 out[3] = in[3];
310                 in += 4;
311                 out += 4;
312         }
313 }
314
315 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
316 {
317         int i;
318         for (i = 0;i < verts;i++)
319         {
320                 out[0] = r;
321                 out[1] = g;
322                 out[2] = b;
323                 out[3] = a;
324                 out += 4;
325         }
326 }
327
328 // FIXME: move this to client?
329 void FOG_clear(void)
330 {
331         if (gamemode == GAME_NEHAHRA)
332         {
333                 Cvar_Set("gl_fogenable", "0");
334                 Cvar_Set("gl_fogdensity", "0.2");
335                 Cvar_Set("gl_fogred", "0.3");
336                 Cvar_Set("gl_foggreen", "0.3");
337                 Cvar_Set("gl_fogblue", "0.3");
338         }
339         r_refdef.fog_density = 0;
340         r_refdef.fog_red = 0;
341         r_refdef.fog_green = 0;
342         r_refdef.fog_blue = 0;
343         r_refdef.fog_alpha = 1;
344         r_refdef.fog_start = 0;
345         r_refdef.fog_end = 16384;
346         r_refdef.fog_height = 1<<30;
347         r_refdef.fog_fadedepth = 128;
348         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
349 }
350
351 static void R_BuildBlankTextures(void)
352 {
353         unsigned char data[4];
354         data[2] = 128; // normal X
355         data[1] = 128; // normal Y
356         data[0] = 255; // normal Z
357         data[3] = 255; // height
358         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 255;
360         data[1] = 255;
361         data[2] = 255;
362         data[3] = 255;
363         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364         data[0] = 128;
365         data[1] = 128;
366         data[2] = 128;
367         data[3] = 255;
368         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369         data[0] = 0;
370         data[1] = 0;
371         data[2] = 0;
372         data[3] = 255;
373         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 }
375
376 static void R_BuildNoTexture(void)
377 {
378         int x, y;
379         unsigned char pix[16][16][4];
380         // this makes a light grey/dark grey checkerboard texture
381         for (y = 0;y < 16;y++)
382         {
383                 for (x = 0;x < 16;x++)
384                 {
385                         if ((y < 8) ^ (x < 8))
386                         {
387                                 pix[y][x][0] = 128;
388                                 pix[y][x][1] = 128;
389                                 pix[y][x][2] = 128;
390                                 pix[y][x][3] = 255;
391                         }
392                         else
393                         {
394                                 pix[y][x][0] = 64;
395                                 pix[y][x][1] = 64;
396                                 pix[y][x][2] = 64;
397                                 pix[y][x][3] = 255;
398                         }
399                 }
400         }
401         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
402 }
403
404 static void R_BuildWhiteCube(void)
405 {
406         unsigned char data[6*1*1*4];
407         memset(data, 255, sizeof(data));
408         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
409 }
410
411 static void R_BuildNormalizationCube(void)
412 {
413         int x, y, side;
414         vec3_t v;
415         vec_t s, t, intensity;
416 #define NORMSIZE 64
417         unsigned char *data;
418         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
419         for (side = 0;side < 6;side++)
420         {
421                 for (y = 0;y < NORMSIZE;y++)
422                 {
423                         for (x = 0;x < NORMSIZE;x++)
424                         {
425                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427                                 switch(side)
428                                 {
429                                 default:
430                                 case 0:
431                                         v[0] = 1;
432                                         v[1] = -t;
433                                         v[2] = -s;
434                                         break;
435                                 case 1:
436                                         v[0] = -1;
437                                         v[1] = -t;
438                                         v[2] = s;
439                                         break;
440                                 case 2:
441                                         v[0] = s;
442                                         v[1] = 1;
443                                         v[2] = t;
444                                         break;
445                                 case 3:
446                                         v[0] = s;
447                                         v[1] = -1;
448                                         v[2] = -t;
449                                         break;
450                                 case 4:
451                                         v[0] = s;
452                                         v[1] = -t;
453                                         v[2] = 1;
454                                         break;
455                                 case 5:
456                                         v[0] = -s;
457                                         v[1] = -t;
458                                         v[2] = -1;
459                                         break;
460                                 }
461                                 intensity = 127.0f / sqrt(DotProduct(v, v));
462                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
463                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
464                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
465                                 data[((side*64+y)*64+x)*4+3] = 255;
466                         }
467                 }
468         }
469         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
470         Mem_Free(data);
471 }
472
473 static void R_BuildFogTexture(void)
474 {
475         int x, b;
476 #define FOGWIDTH 256
477         unsigned char data1[FOGWIDTH][4];
478         //unsigned char data2[FOGWIDTH][4];
479         double d, r, alpha;
480
481         r_refdef.fogmasktable_start = r_refdef.fog_start;
482         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
483         r_refdef.fogmasktable_range = r_refdef.fogrange;
484         r_refdef.fogmasktable_density = r_refdef.fog_density;
485
486         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
487         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
488         {
489                 d = (x * r - r_refdef.fogmasktable_start);
490                 if(developer_extra.integer)
491                         Con_DPrintf("%f ", d);
492                 d = max(0, d);
493                 if (r_fog_exp2.integer)
494                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
495                 else
496                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
497                 if(developer_extra.integer)
498                         Con_DPrintf(" : %f ", alpha);
499                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
500                 if(developer_extra.integer)
501                         Con_DPrintf(" = %f\n", alpha);
502                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
503         }
504
505         for (x = 0;x < FOGWIDTH;x++)
506         {
507                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508                 data1[x][0] = b;
509                 data1[x][1] = b;
510                 data1[x][2] = b;
511                 data1[x][3] = 255;
512                 //data2[x][0] = 255 - b;
513                 //data2[x][1] = 255 - b;
514                 //data2[x][2] = 255 - b;
515                 //data2[x][3] = 255;
516         }
517         if (r_texture_fogattenuation)
518         {
519                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521         }
522         else
523         {
524                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
525                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
526         }
527 }
528
529 static void R_BuildFogHeightTexture(void)
530 {
531         unsigned char *inpixels;
532         int size;
533         int x;
534         int y;
535         int j;
536         float c[4];
537         float f;
538         inpixels = NULL;
539         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
540         if (r_refdef.fogheighttexturename[0])
541                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
542         if (!inpixels)
543         {
544                 r_refdef.fog_height_tablesize = 0;
545                 if (r_texture_fogheighttexture)
546                         R_FreeTexture(r_texture_fogheighttexture);
547                 r_texture_fogheighttexture = NULL;
548                 if (r_refdef.fog_height_table2d)
549                         Mem_Free(r_refdef.fog_height_table2d);
550                 r_refdef.fog_height_table2d = NULL;
551                 if (r_refdef.fog_height_table1d)
552                         Mem_Free(r_refdef.fog_height_table1d);
553                 r_refdef.fog_height_table1d = NULL;
554                 return;
555         }
556         size = image_width;
557         r_refdef.fog_height_tablesize = size;
558         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
559         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
560         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
561         Mem_Free(inpixels);
562         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
563         // average fog color table accounting for every fog layer between a point
564         // and the camera.  (Note: attenuation is handled separately!)
565         for (y = 0;y < size;y++)
566         {
567                 for (x = 0;x < size;x++)
568                 {
569                         Vector4Clear(c);
570                         f = 0;
571                         if (x < y)
572                         {
573                                 for (j = x;j <= y;j++)
574                                 {
575                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
576                                         f++;
577                                 }
578                         }
579                         else
580                         {
581                                 for (j = x;j >= y;j--)
582                                 {
583                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584                                         f++;
585                                 }
586                         }
587                         f = 1.0f / f;
588                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
591                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
592                 }
593         }
594         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
595 }
596
597 //=======================================================================================================================================================
598
599 static const char *builtinshaderstring =
600 #include "shader_glsl.h"
601 ;
602
603 const char *builtinhlslshaderstring =
604 #include "shader_hlsl.h"
605 ;
606
607 char *glslshaderstring = NULL;
608 char *hlslshaderstring = NULL;
609
610 //=======================================================================================================================================================
611
612 typedef struct shaderpermutationinfo_s
613 {
614         const char *pretext;
615         const char *name;
616 }
617 shaderpermutationinfo_t;
618
619 typedef struct shadermodeinfo_s
620 {
621         const char *vertexfilename;
622         const char *geometryfilename;
623         const char *fragmentfilename;
624         const char *pretext;
625         const char *name;
626 }
627 shadermodeinfo_t;
628
629 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
630 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
631 {
632         {"#define USEDIFFUSE\n", " diffuse"},
633         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
634         {"#define USEVIEWTINT\n", " viewtint"},
635         {"#define USECOLORMAPPING\n", " colormapping"},
636         {"#define USESATURATION\n", " saturation"},
637         {"#define USEFOGINSIDE\n", " foginside"},
638         {"#define USEFOGOUTSIDE\n", " fogoutside"},
639         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
640         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
641         {"#define USEGAMMARAMPS\n", " gammaramps"},
642         {"#define USECUBEFILTER\n", " cubefilter"},
643         {"#define USEGLOW\n", " glow"},
644         {"#define USEBLOOM\n", " bloom"},
645         {"#define USESPECULAR\n", " specular"},
646         {"#define USEPOSTPROCESSING\n", " postprocessing"},
647         {"#define USEREFLECTION\n", " reflection"},
648         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
649         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
650         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
651         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
652         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
653         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
654         {"#define USEALPHAKILL\n", " alphakill"},
655         {"#define USEREFLECTCUBE\n", " reflectcube"},
656         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
657         {"#define USEBOUNCEGRID\n", " bouncegrid"},
658         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
659         {"#define USETRIPPY\n", " trippy"},
660         {"#define USEDEPTHRGB\n", " depthrgb"},
661         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
662 };
663
664 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
665 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
666 {
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
685 };
686
687 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
688 {
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707 };
708
709 struct r_glsl_permutation_s;
710 typedef struct r_glsl_permutation_s
711 {
712         /// hash lookup data
713         struct r_glsl_permutation_s *hashnext;
714         unsigned int mode;
715         unsigned int permutation;
716
717         /// indicates if we have tried compiling this permutation already
718         qboolean compiled;
719         /// 0 if compilation failed
720         int program;
721         // texture units assigned to each detected uniform
722         int tex_Texture_First;
723         int tex_Texture_Second;
724         int tex_Texture_GammaRamps;
725         int tex_Texture_Normal;
726         int tex_Texture_Color;
727         int tex_Texture_Gloss;
728         int tex_Texture_Glow;
729         int tex_Texture_SecondaryNormal;
730         int tex_Texture_SecondaryColor;
731         int tex_Texture_SecondaryGloss;
732         int tex_Texture_SecondaryGlow;
733         int tex_Texture_Pants;
734         int tex_Texture_Shirt;
735         int tex_Texture_FogHeightTexture;
736         int tex_Texture_FogMask;
737         int tex_Texture_Lightmap;
738         int tex_Texture_Deluxemap;
739         int tex_Texture_Attenuation;
740         int tex_Texture_Cube;
741         int tex_Texture_Refraction;
742         int tex_Texture_Reflection;
743         int tex_Texture_ShadowMap2D;
744         int tex_Texture_CubeProjection;
745         int tex_Texture_ScreenNormalMap;
746         int tex_Texture_ScreenDiffuse;
747         int tex_Texture_ScreenSpecular;
748         int tex_Texture_ReflectMask;
749         int tex_Texture_ReflectCube;
750         int tex_Texture_BounceGrid;
751         /// locations of detected uniforms in program object, or -1 if not found
752         int loc_Texture_First;
753         int loc_Texture_Second;
754         int loc_Texture_GammaRamps;
755         int loc_Texture_Normal;
756         int loc_Texture_Color;
757         int loc_Texture_Gloss;
758         int loc_Texture_Glow;
759         int loc_Texture_SecondaryNormal;
760         int loc_Texture_SecondaryColor;
761         int loc_Texture_SecondaryGloss;
762         int loc_Texture_SecondaryGlow;
763         int loc_Texture_Pants;
764         int loc_Texture_Shirt;
765         int loc_Texture_FogHeightTexture;
766         int loc_Texture_FogMask;
767         int loc_Texture_Lightmap;
768         int loc_Texture_Deluxemap;
769         int loc_Texture_Attenuation;
770         int loc_Texture_Cube;
771         int loc_Texture_Refraction;
772         int loc_Texture_Reflection;
773         int loc_Texture_ShadowMap2D;
774         int loc_Texture_CubeProjection;
775         int loc_Texture_ScreenNormalMap;
776         int loc_Texture_ScreenDiffuse;
777         int loc_Texture_ScreenSpecular;
778         int loc_Texture_ReflectMask;
779         int loc_Texture_ReflectCube;
780         int loc_Texture_BounceGrid;
781         int loc_Alpha;
782         int loc_BloomBlur_Parameters;
783         int loc_ClientTime;
784         int loc_Color_Ambient;
785         int loc_Color_Diffuse;
786         int loc_Color_Specular;
787         int loc_Color_Glow;
788         int loc_Color_Pants;
789         int loc_Color_Shirt;
790         int loc_DeferredColor_Ambient;
791         int loc_DeferredColor_Diffuse;
792         int loc_DeferredColor_Specular;
793         int loc_DeferredMod_Diffuse;
794         int loc_DeferredMod_Specular;
795         int loc_DistortScaleRefractReflect;
796         int loc_EyePosition;
797         int loc_FogColor;
798         int loc_FogHeightFade;
799         int loc_FogPlane;
800         int loc_FogPlaneViewDist;
801         int loc_FogRangeRecip;
802         int loc_LightColor;
803         int loc_LightDir;
804         int loc_LightPosition;
805         int loc_OffsetMapping_ScaleSteps;
806         int loc_OffsetMapping_LodDistance;
807         int loc_OffsetMapping_Bias;
808         int loc_PixelSize;
809         int loc_ReflectColor;
810         int loc_ReflectFactor;
811         int loc_ReflectOffset;
812         int loc_RefractColor;
813         int loc_Saturation;
814         int loc_ScreenCenterRefractReflect;
815         int loc_ScreenScaleRefractReflect;
816         int loc_ScreenToDepth;
817         int loc_ShadowMap_Parameters;
818         int loc_ShadowMap_TextureScale;
819         int loc_SpecularPower;
820         int loc_UserVec1;
821         int loc_UserVec2;
822         int loc_UserVec3;
823         int loc_UserVec4;
824         int loc_ViewTintColor;
825         int loc_ViewToLight;
826         int loc_ModelToLight;
827         int loc_TexMatrix;
828         int loc_BackgroundTexMatrix;
829         int loc_ModelViewProjectionMatrix;
830         int loc_ModelViewMatrix;
831         int loc_PixelToScreenTexCoord;
832         int loc_ModelToReflectCube;
833         int loc_ShadowMapMatrix;
834         int loc_BloomColorSubtract;
835         int loc_NormalmapScrollBlend;
836         int loc_BounceGridMatrix;
837         int loc_BounceGridIntensity;
838 }
839 r_glsl_permutation_t;
840
841 #define SHADERPERMUTATION_HASHSIZE 256
842
843
844 // non-degradable "lightweight" shader parameters to keep the permutations simpler
845 // these can NOT degrade! only use for simple stuff
846 enum
847 {
848         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
849         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
850         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
851         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
853         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
854         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
855         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
856         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
857         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
858         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
859         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
860         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
861 };
862 #define SHADERSTATICPARMS_COUNT 13
863
864 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
865 static int shaderstaticparms_count = 0;
866
867 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
868 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
869
870 extern qboolean r_shadow_shadowmapsampler;
871 extern int r_shadow_shadowmappcf;
872 qboolean R_CompileShader_CheckStaticParms(void)
873 {
874         static int r_compileshader_staticparms_save[1];
875         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
876         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
877
878         // detect all
879         if (r_glsl_saturation_redcompensate.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
881         if (r_glsl_vertextextureblend_usebothalphas.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
883         if (r_shadow_glossexact.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
885         if (r_glsl_postprocess.integer)
886         {
887                 if (r_glsl_postprocess_uservec1_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
889                 if (r_glsl_postprocess_uservec2_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
891                 if (r_glsl_postprocess_uservec3_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
893                 if (r_glsl_postprocess_uservec4_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
895         }
896         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
898
899         if (r_shadow_shadowmapsampler)
900                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
901         if (r_shadow_shadowmappcf > 1)
902                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
903         else if (r_shadow_shadowmappcf)
904                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
905         if (r_celshading.integer)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
907         if (r_celoutlines.integer)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
909
910         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
911 }
912
913 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
914         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
915                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
916         else \
917                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
918 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
919 {
920         shaderstaticparms_count = 0;
921
922         // emit all
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
936 }
937
938 /// information about each possible shader permutation
939 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
940 /// currently selected permutation
941 r_glsl_permutation_t *r_glsl_permutation;
942 /// storage for permutations linked in the hash table
943 memexpandablearray_t r_glsl_permutationarray;
944
945 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
946 {
947         //unsigned int hashdepth = 0;
948         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
949         r_glsl_permutation_t *p;
950         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
951         {
952                 if (p->mode == mode && p->permutation == permutation)
953                 {
954                         //if (hashdepth > 10)
955                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956                         return p;
957                 }
958                 //hashdepth++;
959         }
960         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
961         p->mode = mode;
962         p->permutation = permutation;
963         p->hashnext = r_glsl_permutationhash[mode][hashindex];
964         r_glsl_permutationhash[mode][hashindex] = p;
965         //if (hashdepth > 10)
966         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
967         return p;
968 }
969
970 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
971 {
972         char *shaderstring;
973         if (!filename || !filename[0])
974                 return NULL;
975         if (!strcmp(filename, "glsl/default.glsl"))
976         {
977                 if (!glslshaderstring)
978                 {
979                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980                         if (glslshaderstring)
981                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
982                         else
983                                 glslshaderstring = (char *)builtinshaderstring;
984                 }
985                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
986                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
987                 return shaderstring;
988         }
989         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
990         if (shaderstring)
991         {
992                 if (printfromdisknotice)
993                         Con_DPrintf("from disk %s... ", filename);
994                 return shaderstring;
995         }
996         return shaderstring;
997 }
998
999 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1000 {
1001         int i;
1002         int sampler;
1003         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1004         char *vertexstring, *geometrystring, *fragmentstring;
1005         char permutationname[256];
1006         int vertstrings_count = 0;
1007         int geomstrings_count = 0;
1008         int fragstrings_count = 0;
1009         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1010         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1011         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1012
1013         if (p->compiled)
1014                 return;
1015         p->compiled = true;
1016         p->program = 0;
1017
1018         permutationname[0] = 0;
1019         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1020         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1021         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1022
1023         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1024
1025         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1026         if(vid.support.gl20shaders130)
1027         {
1028                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1029                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1030                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1031                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1032                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1033                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1034         }
1035
1036         // the first pretext is which type of shader to compile as
1037         // (later these will all be bound together as a program object)
1038         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1039         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1040         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1041
1042         // the second pretext is the mode (for example a light source)
1043         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1044         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1045         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1046         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1047
1048         // now add all the permutation pretexts
1049         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1050         {
1051                 if (permutation & (1<<i))
1052                 {
1053                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1056                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1057                 }
1058                 else
1059                 {
1060                         // keep line numbers correct
1061                         vertstrings_list[vertstrings_count++] = "\n";
1062                         geomstrings_list[geomstrings_count++] = "\n";
1063                         fragstrings_list[fragstrings_count++] = "\n";
1064                 }
1065         }
1066
1067         // add static parms
1068         R_CompileShader_AddStaticParms(mode, permutation);
1069         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070         vertstrings_count += shaderstaticparms_count;
1071         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072         geomstrings_count += shaderstaticparms_count;
1073         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1074         fragstrings_count += shaderstaticparms_count;
1075
1076         // now append the shader text itself
1077         vertstrings_list[vertstrings_count++] = vertexstring;
1078         geomstrings_list[geomstrings_count++] = geometrystring;
1079         fragstrings_list[fragstrings_count++] = fragmentstring;
1080
1081         // if any sources were NULL, clear the respective list
1082         if (!vertexstring)
1083                 vertstrings_count = 0;
1084         if (!geometrystring)
1085                 geomstrings_count = 0;
1086         if (!fragmentstring)
1087                 fragstrings_count = 0;
1088
1089         // compile the shader program
1090         if (vertstrings_count + geomstrings_count + fragstrings_count)
1091                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1092         if (p->program)
1093         {
1094                 CHECKGLERROR
1095                 qglUseProgram(p->program);CHECKGLERROR
1096                 // look up all the uniform variable names we care about, so we don't
1097                 // have to look them up every time we set them
1098
1099                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1100                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1101                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1102                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1103                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1104                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1105                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1106                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1107                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1108                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1109                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1110                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1111                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1112                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1113                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1114                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1115                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1116                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1117                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1118                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1119                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1120                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1121                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1122                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1123                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1124                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1125                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1126                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1127                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1128                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1129                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1130                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1131                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1132                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1133                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1134                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1135                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1136                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1137                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1138                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1139                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1140                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1141                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1142                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1143                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1144                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1145                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1146                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1147                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1148                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1149                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1150                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1151                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1152                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1153                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1154                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1155                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1156                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1157                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1158                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1159                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1160                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1161                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1162                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1163                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1164                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1165                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1166                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1167                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1168                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1169                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1170                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1171                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1172                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1173                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1174                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1175                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1176                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1177                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1178                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1179                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1180                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1181                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1182                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1183                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1184                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1185                 // initialize the samplers to refer to the texture units we use
1186                 p->tex_Texture_First = -1;
1187                 p->tex_Texture_Second = -1;
1188                 p->tex_Texture_GammaRamps = -1;
1189                 p->tex_Texture_Normal = -1;
1190                 p->tex_Texture_Color = -1;
1191                 p->tex_Texture_Gloss = -1;
1192                 p->tex_Texture_Glow = -1;
1193                 p->tex_Texture_SecondaryNormal = -1;
1194                 p->tex_Texture_SecondaryColor = -1;
1195                 p->tex_Texture_SecondaryGloss = -1;
1196                 p->tex_Texture_SecondaryGlow = -1;
1197                 p->tex_Texture_Pants = -1;
1198                 p->tex_Texture_Shirt = -1;
1199                 p->tex_Texture_FogHeightTexture = -1;
1200                 p->tex_Texture_FogMask = -1;
1201                 p->tex_Texture_Lightmap = -1;
1202                 p->tex_Texture_Deluxemap = -1;
1203                 p->tex_Texture_Attenuation = -1;
1204                 p->tex_Texture_Cube = -1;
1205                 p->tex_Texture_Refraction = -1;
1206                 p->tex_Texture_Reflection = -1;
1207                 p->tex_Texture_ShadowMap2D = -1;
1208                 p->tex_Texture_CubeProjection = -1;
1209                 p->tex_Texture_ScreenNormalMap = -1;
1210                 p->tex_Texture_ScreenDiffuse = -1;
1211                 p->tex_Texture_ScreenSpecular = -1;
1212                 p->tex_Texture_ReflectMask = -1;
1213                 p->tex_Texture_ReflectCube = -1;
1214                 p->tex_Texture_BounceGrid = -1;
1215                 sampler = 0;
1216                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1217                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1218                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1219                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1220                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1221                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1222                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1227                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1228                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1229                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1230                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1231                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1232                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1233                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1234                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1235                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1236                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1237                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1238                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1243                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1244                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1245                 CHECKGLERROR
1246                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1247         }
1248         else
1249                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1250
1251         // free the strings
1252         if (vertexstring)
1253                 Mem_Free(vertexstring);
1254         if (geometrystring)
1255                 Mem_Free(geometrystring);
1256         if (fragmentstring)
1257                 Mem_Free(fragmentstring);
1258 }
1259
1260 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1261 {
1262         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1263         if (r_glsl_permutation != perm)
1264         {
1265                 r_glsl_permutation = perm;
1266                 if (!r_glsl_permutation->program)
1267                 {
1268                         if (!r_glsl_permutation->compiled)
1269                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1270                         if (!r_glsl_permutation->program)
1271                         {
1272                                 // remove features until we find a valid permutation
1273                                 int i;
1274                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1275                                 {
1276                                         // reduce i more quickly whenever it would not remove any bits
1277                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1278                                         if (!(permutation & j))
1279                                                 continue;
1280                                         permutation -= j;
1281                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282                                         if (!r_glsl_permutation->compiled)
1283                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1284                                         if (r_glsl_permutation->program)
1285                                                 break;
1286                                 }
1287                                 if (i >= SHADERPERMUTATION_COUNT)
1288                                 {
1289                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1290                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291                                         qglUseProgram(0);CHECKGLERROR
1292                                         return; // no bit left to clear, entire mode is broken
1293                                 }
1294                         }
1295                 }
1296                 CHECKGLERROR
1297                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1298         }
1299         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1300         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1301         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1302 }
1303
1304 #ifdef SUPPORTD3D
1305
1306 #ifdef SUPPORTD3D
1307 #include <d3d9.h>
1308 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1309 extern D3DCAPS9 vid_d3d9caps;
1310 #endif
1311
1312 struct r_hlsl_permutation_s;
1313 typedef struct r_hlsl_permutation_s
1314 {
1315         /// hash lookup data
1316         struct r_hlsl_permutation_s *hashnext;
1317         unsigned int mode;
1318         unsigned int permutation;
1319
1320         /// indicates if we have tried compiling this permutation already
1321         qboolean compiled;
1322         /// NULL if compilation failed
1323         IDirect3DVertexShader9 *vertexshader;
1324         IDirect3DPixelShader9 *pixelshader;
1325 }
1326 r_hlsl_permutation_t;
1327
1328 typedef enum D3DVSREGISTER_e
1329 {
1330         D3DVSREGISTER_TexMatrix = 0, // float4x4
1331         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1332         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1333         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1334         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1335         D3DVSREGISTER_ModelToLight = 20, // float4x4
1336         D3DVSREGISTER_EyePosition = 24,
1337         D3DVSREGISTER_FogPlane = 25,
1338         D3DVSREGISTER_LightDir = 26,
1339         D3DVSREGISTER_LightPosition = 27,
1340 }
1341 D3DVSREGISTER_t;
1342
1343 typedef enum D3DPSREGISTER_e
1344 {
1345         D3DPSREGISTER_Alpha = 0,
1346         D3DPSREGISTER_BloomBlur_Parameters = 1,
1347         D3DPSREGISTER_ClientTime = 2,
1348         D3DPSREGISTER_Color_Ambient = 3,
1349         D3DPSREGISTER_Color_Diffuse = 4,
1350         D3DPSREGISTER_Color_Specular = 5,
1351         D3DPSREGISTER_Color_Glow = 6,
1352         D3DPSREGISTER_Color_Pants = 7,
1353         D3DPSREGISTER_Color_Shirt = 8,
1354         D3DPSREGISTER_DeferredColor_Ambient = 9,
1355         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1356         D3DPSREGISTER_DeferredColor_Specular = 11,
1357         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1358         D3DPSREGISTER_DeferredMod_Specular = 13,
1359         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1360         D3DPSREGISTER_EyePosition = 15, // unused
1361         D3DPSREGISTER_FogColor = 16,
1362         D3DPSREGISTER_FogHeightFade = 17,
1363         D3DPSREGISTER_FogPlane = 18,
1364         D3DPSREGISTER_FogPlaneViewDist = 19,
1365         D3DPSREGISTER_FogRangeRecip = 20,
1366         D3DPSREGISTER_LightColor = 21,
1367         D3DPSREGISTER_LightDir = 22, // unused
1368         D3DPSREGISTER_LightPosition = 23,
1369         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1370         D3DPSREGISTER_PixelSize = 25,
1371         D3DPSREGISTER_ReflectColor = 26,
1372         D3DPSREGISTER_ReflectFactor = 27,
1373         D3DPSREGISTER_ReflectOffset = 28,
1374         D3DPSREGISTER_RefractColor = 29,
1375         D3DPSREGISTER_Saturation = 30,
1376         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1377         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1378         D3DPSREGISTER_ScreenToDepth = 33,
1379         D3DPSREGISTER_ShadowMap_Parameters = 34,
1380         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1381         D3DPSREGISTER_SpecularPower = 36,
1382         D3DPSREGISTER_UserVec1 = 37,
1383         D3DPSREGISTER_UserVec2 = 38,
1384         D3DPSREGISTER_UserVec3 = 39,
1385         D3DPSREGISTER_UserVec4 = 40,
1386         D3DPSREGISTER_ViewTintColor = 41,
1387         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1388         D3DPSREGISTER_BloomColorSubtract = 43,
1389         D3DPSREGISTER_ViewToLight = 44, // float4x4
1390         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1391         D3DPSREGISTER_NormalmapScrollBlend = 52,
1392         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1393         D3DPSREGISTER_OffsetMapping_Bias = 54,
1394         // next at 54
1395 }
1396 D3DPSREGISTER_t;
1397
1398 /// information about each possible shader permutation
1399 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1400 /// currently selected permutation
1401 r_hlsl_permutation_t *r_hlsl_permutation;
1402 /// storage for permutations linked in the hash table
1403 memexpandablearray_t r_hlsl_permutationarray;
1404
1405 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1406 {
1407         //unsigned int hashdepth = 0;
1408         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1409         r_hlsl_permutation_t *p;
1410         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1411         {
1412                 if (p->mode == mode && p->permutation == permutation)
1413                 {
1414                         //if (hashdepth > 10)
1415                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416                         return p;
1417                 }
1418                 //hashdepth++;
1419         }
1420         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1421         p->mode = mode;
1422         p->permutation = permutation;
1423         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1424         r_hlsl_permutationhash[mode][hashindex] = p;
1425         //if (hashdepth > 10)
1426         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1427         return p;
1428 }
1429
1430 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1431 {
1432         char *shaderstring;
1433         if (!filename || !filename[0])
1434                 return NULL;
1435         if (!strcmp(filename, "hlsl/default.hlsl"))
1436         {
1437                 if (!hlslshaderstring)
1438                 {
1439                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1440                         if (hlslshaderstring)
1441                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1442                         else
1443                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1444                 }
1445                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1446                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1447                 return shaderstring;
1448         }
1449         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1450         if (shaderstring)
1451         {
1452                 if (printfromdisknotice)
1453                         Con_DPrintf("from disk %s... ", filename);
1454                 return shaderstring;
1455         }
1456         return shaderstring;
1457 }
1458
1459 #include <d3dx9.h>
1460 //#include <d3dx9shader.h>
1461 //#include <d3dx9mesh.h>
1462
1463 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1464 {
1465         DWORD *vsbin = NULL;
1466         DWORD *psbin = NULL;
1467         fs_offset_t vsbinsize;
1468         fs_offset_t psbinsize;
1469 //      IDirect3DVertexShader9 *vs = NULL;
1470 //      IDirect3DPixelShader9 *ps = NULL;
1471         ID3DXBuffer *vslog = NULL;
1472         ID3DXBuffer *vsbuffer = NULL;
1473         ID3DXConstantTable *vsconstanttable = NULL;
1474         ID3DXBuffer *pslog = NULL;
1475         ID3DXBuffer *psbuffer = NULL;
1476         ID3DXConstantTable *psconstanttable = NULL;
1477         int vsresult = 0;
1478         int psresult = 0;
1479         char temp[MAX_INPUTLINE];
1480         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1481         char vabuf[1024];
1482         qboolean debugshader = gl_paranoid.integer != 0;
1483         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485         if (!debugshader)
1486         {
1487                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1488                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1489         }
1490         if ((!vsbin && vertstring) || (!psbin && fragstring))
1491         {
1492                 const char* dllnames_d3dx9 [] =
1493                 {
1494                         "d3dx9_43.dll",
1495                         "d3dx9_42.dll",
1496                         "d3dx9_41.dll",
1497                         "d3dx9_40.dll",
1498                         "d3dx9_39.dll",
1499                         "d3dx9_38.dll",
1500                         "d3dx9_37.dll",
1501                         "d3dx9_36.dll",
1502                         "d3dx9_35.dll",
1503                         "d3dx9_34.dll",
1504                         "d3dx9_33.dll",
1505                         "d3dx9_32.dll",
1506                         "d3dx9_31.dll",
1507                         "d3dx9_30.dll",
1508                         "d3dx9_29.dll",
1509                         "d3dx9_28.dll",
1510                         "d3dx9_27.dll",
1511                         "d3dx9_26.dll",
1512                         "d3dx9_25.dll",
1513                         "d3dx9_24.dll",
1514                         NULL
1515                 };
1516                 dllhandle_t d3dx9_dll = NULL;
1517                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1519                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1520                 dllfunction_t d3dx9_dllfuncs[] =
1521                 {
1522                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1523                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1524                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1525                         {NULL, NULL}
1526                 };
1527                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1528                 {
1529                         DWORD shaderflags = 0;
1530                         if (debugshader)
1531                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1532                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1533                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1534                         if (vertstring && vertstring[0])
1535                         {
1536                                 if (debugshader)
1537                                 {
1538 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1539 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1540                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1541                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1542                                 }
1543                                 else
1544                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1545                                 if (vsbuffer)
1546                                 {
1547                                         vsbinsize = vsbuffer->GetBufferSize();
1548                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1549                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1550                                         vsbuffer->Release();
1551                                 }
1552                                 if (vslog)
1553                                 {
1554                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1555                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1556                                         vslog->Release();
1557                                 }
1558                         }
1559                         if (fragstring && fragstring[0])
1560                         {
1561                                 if (debugshader)
1562                                 {
1563 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1564 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1565                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1566                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567                                 }
1568                                 else
1569                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1570                                 if (psbuffer)
1571                                 {
1572                                         psbinsize = psbuffer->GetBufferSize();
1573                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1574                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1575                                         psbuffer->Release();
1576                                 }
1577                                 if (pslog)
1578                                 {
1579                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1580                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1581                                         pslog->Release();
1582                                 }
1583                         }
1584                         Sys_UnloadLibrary(&d3dx9_dll);
1585                 }
1586                 else
1587                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1588         }
1589         if (vsbin && psbin)
1590         {
1591                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1592                 if (FAILED(vsresult))
1593                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1594                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1595                 if (FAILED(psresult))
1596                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1597         }
1598         // free the shader data
1599         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1600         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1601 }
1602
1603 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1604 {
1605         int i;
1606         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1607         int vertstring_length = 0;
1608         int geomstring_length = 0;
1609         int fragstring_length = 0;
1610         char *t;
1611         char *vertexstring, *geometrystring, *fragmentstring;
1612         char *vertstring, *geomstring, *fragstring;
1613         char permutationname[256];
1614         char cachename[256];
1615         int vertstrings_count = 0;
1616         int geomstrings_count = 0;
1617         int fragstrings_count = 0;
1618         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1619         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1620         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1621
1622         if (p->compiled)
1623                 return;
1624         p->compiled = true;
1625         p->vertexshader = NULL;
1626         p->pixelshader = NULL;
1627
1628         permutationname[0] = 0;
1629         cachename[0] = 0;
1630         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1631         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1632         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1633
1634         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1635         strlcat(cachename, "hlsl/", sizeof(cachename));
1636
1637         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1638         vertstrings_count = 0;
1639         geomstrings_count = 0;
1640         fragstrings_count = 0;
1641         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1642         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1643         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1644
1645         // the first pretext is which type of shader to compile as
1646         // (later these will all be bound together as a program object)
1647         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1648         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1649         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1650
1651         // the second pretext is the mode (for example a light source)
1652         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1653         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1654         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1655         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1656         strlcat(cachename, modeinfo->name, sizeof(cachename));
1657
1658         // now add all the permutation pretexts
1659         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1660         {
1661                 if (permutation & (1<<i))
1662                 {
1663                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1667                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1668                 }
1669                 else
1670                 {
1671                         // keep line numbers correct
1672                         vertstrings_list[vertstrings_count++] = "\n";
1673                         geomstrings_list[geomstrings_count++] = "\n";
1674                         fragstrings_list[fragstrings_count++] = "\n";
1675                 }
1676         }
1677
1678         // add static parms
1679         R_CompileShader_AddStaticParms(mode, permutation);
1680         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681         vertstrings_count += shaderstaticparms_count;
1682         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         geomstrings_count += shaderstaticparms_count;
1684         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685         fragstrings_count += shaderstaticparms_count;
1686
1687         // replace spaces in the cachename with _ characters
1688         for (i = 0;cachename[i];i++)
1689                 if (cachename[i] == ' ')
1690                         cachename[i] = '_';
1691
1692         // now append the shader text itself
1693         vertstrings_list[vertstrings_count++] = vertexstring;
1694         geomstrings_list[geomstrings_count++] = geometrystring;
1695         fragstrings_list[fragstrings_count++] = fragmentstring;
1696
1697         // if any sources were NULL, clear the respective list
1698         if (!vertexstring)
1699                 vertstrings_count = 0;
1700         if (!geometrystring)
1701                 geomstrings_count = 0;
1702         if (!fragmentstring)
1703                 fragstrings_count = 0;
1704
1705         vertstring_length = 0;
1706         for (i = 0;i < vertstrings_count;i++)
1707                 vertstring_length += strlen(vertstrings_list[i]);
1708         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1709         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1710                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1711
1712         geomstring_length = 0;
1713         for (i = 0;i < geomstrings_count;i++)
1714                 geomstring_length += strlen(geomstrings_list[i]);
1715         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1716         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1717                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1718
1719         fragstring_length = 0;
1720         for (i = 0;i < fragstrings_count;i++)
1721                 fragstring_length += strlen(fragstrings_list[i]);
1722         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1723         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1724                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1725
1726         // try to load the cached shader, or generate one
1727         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1728
1729         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1730                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1731         else
1732                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1733
1734         // free the strings
1735         if (vertstring)
1736                 Mem_Free(vertstring);
1737         if (geomstring)
1738                 Mem_Free(geomstring);
1739         if (fragstring)
1740                 Mem_Free(fragstring);
1741         if (vertexstring)
1742                 Mem_Free(vertexstring);
1743         if (geometrystring)
1744                 Mem_Free(geometrystring);
1745         if (fragmentstring)
1746                 Mem_Free(fragmentstring);
1747 }
1748
1749 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1750 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1751 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);}
1752 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);}
1753 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);}
1754 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);}
1755
1756 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1757 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1758 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);}
1759 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);}
1760 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);}
1761 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);}
1762
1763 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1764 {
1765         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1766         if (r_hlsl_permutation != perm)
1767         {
1768                 r_hlsl_permutation = perm;
1769                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1770                 {
1771                         if (!r_hlsl_permutation->compiled)
1772                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1773                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1774                         {
1775                                 // remove features until we find a valid permutation
1776                                 int i;
1777                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778                                 {
1779                                         // reduce i more quickly whenever it would not remove any bits
1780                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1781                                         if (!(permutation & j))
1782                                                 continue;
1783                                         permutation -= j;
1784                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1785                                         if (!r_hlsl_permutation->compiled)
1786                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1787                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1788                                                 break;
1789                                 }
1790                                 if (i >= SHADERPERMUTATION_COUNT)
1791                                 {
1792                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1793                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1794                                         return; // no bit left to clear, entire mode is broken
1795                                 }
1796                         }
1797                 }
1798                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1799                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1800         }
1801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1802         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1803         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1804 }
1805 #endif
1806
1807 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1808 {
1809         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1810         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1811         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1812         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1813 }
1814
1815 void R_GLSL_Restart_f(void)
1816 {
1817         unsigned int i, limit;
1818         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1819                 Mem_Free(glslshaderstring);
1820         glslshaderstring = NULL;
1821         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1822                 Mem_Free(hlslshaderstring);
1823         hlslshaderstring = NULL;
1824         switch(vid.renderpath)
1825         {
1826         case RENDERPATH_D3D9:
1827 #ifdef SUPPORTD3D
1828                 {
1829                         r_hlsl_permutation_t *p;
1830                         r_hlsl_permutation = NULL;
1831                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1832                         for (i = 0;i < limit;i++)
1833                         {
1834                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1835                                 {
1836                                         if (p->vertexshader)
1837                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1838                                         if (p->pixelshader)
1839                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1840                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1844                 }
1845 #endif
1846                 break;
1847         case RENDERPATH_D3D10:
1848                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1849                 break;
1850         case RENDERPATH_D3D11:
1851                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1852                 break;
1853         case RENDERPATH_GL20:
1854         case RENDERPATH_GLES2:
1855                 {
1856                         r_glsl_permutation_t *p;
1857                         r_glsl_permutation = NULL;
1858                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1859                         for (i = 0;i < limit;i++)
1860                         {
1861                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1862                                 {
1863                                         GL_Backend_FreeProgram(p->program);
1864                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1865                                 }
1866                         }
1867                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1868                 }
1869                 break;
1870         case RENDERPATH_GL11:
1871         case RENDERPATH_GL13:
1872         case RENDERPATH_GLES1:
1873                 break;
1874         case RENDERPATH_SOFT:
1875                 break;
1876         }
1877 }
1878
1879 static void R_GLSL_DumpShader_f(void)
1880 {
1881         int i;
1882         qfile_t *file;
1883
1884         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1885         if (file)
1886         {
1887                 FS_Print(file, "/* The engine may define the following macros:\n");
1888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889                 for (i = 0;i < SHADERMODE_COUNT;i++)
1890                         FS_Print(file, glslshadermodeinfo[i].pretext);
1891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892                         FS_Print(file, shaderpermutationinfo[i].pretext);
1893                 FS_Print(file, "*/\n");
1894                 FS_Print(file, builtinshaderstring);
1895                 FS_Close(file);
1896                 Con_Printf("glsl/default.glsl written\n");
1897         }
1898         else
1899                 Con_Printf("failed to write to glsl/default.glsl\n");
1900
1901         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1902         if (file)
1903         {
1904                 FS_Print(file, "/* The engine may define the following macros:\n");
1905                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1906                 for (i = 0;i < SHADERMODE_COUNT;i++)
1907                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1908                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1909                         FS_Print(file, shaderpermutationinfo[i].pretext);
1910                 FS_Print(file, "*/\n");
1911                 FS_Print(file, builtinhlslshaderstring);
1912                 FS_Close(file);
1913                 Con_Printf("hlsl/default.hlsl written\n");
1914         }
1915         else
1916                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1917 }
1918
1919 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1920 {
1921         unsigned int permutation = 0;
1922         if (r_trippy.integer && !notrippy)
1923                 permutation |= SHADERPERMUTATION_TRIPPY;
1924         permutation |= SHADERPERMUTATION_VIEWTINT;
1925         if (first)
1926                 permutation |= SHADERPERMUTATION_DIFFUSE;
1927         if (second)
1928                 permutation |= SHADERPERMUTATION_SPECULAR;
1929         if (texturemode == GL_MODULATE)
1930                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1931         else if (texturemode == GL_ADD)
1932                 permutation |= SHADERPERMUTATION_GLOW;
1933         else if (texturemode == GL_DECAL)
1934                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1935         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1936                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1937         if (suppresstexalpha)
1938                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1939         if (!second)
1940                 texturemode = GL_MODULATE;
1941         if (vid.allowalphatocoverage)
1942                 GL_AlphaToCoverage(false);
1943         switch (vid.renderpath)
1944         {
1945         case RENDERPATH_D3D9:
1946 #ifdef SUPPORTD3D
1947                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(GL20TU_FIRST , first );
1949                 R_Mesh_TexBind(GL20TU_SECOND, second);
1950                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1951                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952 #endif
1953                 break;
1954         case RENDERPATH_D3D10:
1955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_D3D11:
1958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_GL20:
1961         case RENDERPATH_GLES2:
1962                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1964                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1965                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1966                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1967                 break;
1968         case RENDERPATH_GL13:
1969         case RENDERPATH_GLES1:
1970                 R_Mesh_TexBind(0, first );
1971                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1972                 R_Mesh_TexBind(1, second);
1973                 if (second)
1974                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1975                 break;
1976         case RENDERPATH_GL11:
1977                 R_Mesh_TexBind(0, first );
1978                 break;
1979         case RENDERPATH_SOFT:
1980                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1981                 R_Mesh_TexBind(GL20TU_FIRST , first );
1982                 R_Mesh_TexBind(GL20TU_SECOND, second);
1983                 break;
1984         }
1985 }
1986
1987 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1988 {
1989         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1990 }
1991
1992 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1993 {
1994         unsigned int permutation = 0;
1995         if (r_trippy.integer && !notrippy)
1996                 permutation |= SHADERPERMUTATION_TRIPPY;
1997         if (depthrgb)
1998                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1999         if (vid.allowalphatocoverage)
2000                 GL_AlphaToCoverage(false);
2001         switch (vid.renderpath)
2002         {
2003         case RENDERPATH_D3D9:
2004 #ifdef SUPPORTD3D
2005                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006 #endif
2007                 break;
2008         case RENDERPATH_D3D10:
2009                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2010                 break;
2011         case RENDERPATH_D3D11:
2012                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013                 break;
2014         case RENDERPATH_GL20:
2015         case RENDERPATH_GLES2:
2016                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         case RENDERPATH_GL13:
2019         case RENDERPATH_GLES1:
2020                 R_Mesh_TexBind(0, 0);
2021                 R_Mesh_TexBind(1, 0);
2022                 break;
2023         case RENDERPATH_GL11:
2024                 R_Mesh_TexBind(0, 0);
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2028                 break;
2029         }
2030 }
2031
2032 void R_SetupShader_ShowDepth(qboolean notrippy)
2033 {
2034         int permutation = 0;
2035         if (r_trippy.integer && !notrippy)
2036                 permutation |= SHADERPERMUTATION_TRIPPY;
2037         if (vid.allowalphatocoverage)
2038                 GL_AlphaToCoverage(false);
2039         switch (vid.renderpath)
2040         {
2041         case RENDERPATH_D3D9:
2042 #ifdef SUPPORTHLSL
2043                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2044 #endif
2045                 break;
2046         case RENDERPATH_D3D10:
2047                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2048                 break;
2049         case RENDERPATH_D3D11:
2050                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2051                 break;
2052         case RENDERPATH_GL20:
2053         case RENDERPATH_GLES2:
2054                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2055                 break;
2056         case RENDERPATH_GL13:
2057         case RENDERPATH_GLES1:
2058                 break;
2059         case RENDERPATH_GL11:
2060                 break;
2061         case RENDERPATH_SOFT:
2062                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2063                 break;
2064         }
2065 }
2066
2067 extern qboolean r_shadow_usingdeferredprepass;
2068 extern rtexture_t *r_shadow_attenuationgradienttexture;
2069 extern rtexture_t *r_shadow_attenuation2dtexture;
2070 extern rtexture_t *r_shadow_attenuation3dtexture;
2071 extern qboolean r_shadow_usingshadowmap2d;
2072 extern qboolean r_shadow_usingshadowmaportho;
2073 extern float r_shadow_shadowmap_texturescale[2];
2074 extern float r_shadow_shadowmap_parameters[4];
2075 extern qboolean r_shadow_shadowmapvsdct;
2076 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2077 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2078 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2079 extern matrix4x4_t r_shadow_shadowmapmatrix;
2080 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2081 extern int r_shadow_prepass_width;
2082 extern int r_shadow_prepass_height;
2083 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2084 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2085 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2086 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2087
2088 #define BLENDFUNC_ALLOWS_COLORMOD      1
2089 #define BLENDFUNC_ALLOWS_FOG           2
2090 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2091 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2092 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2093 static int R_BlendFuncFlags(int src, int dst)
2094 {
2095         int r = 0;
2096
2097         // a blendfunc allows colormod if:
2098         // a) it can never keep the destination pixel invariant, or
2099         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2100         // this is to prevent unintended side effects from colormod
2101
2102         // a blendfunc allows fog if:
2103         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2104         // this is to prevent unintended side effects from fog
2105
2106         // these checks are the output of fogeval.pl
2107
2108         r |= BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2116         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2117         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2118         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2120         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2121         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2122         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2123         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2124         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2125         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2126         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2127         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2129         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130
2131         return r;
2132 }
2133
2134 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)
2135 {
2136         // select a permutation of the lighting shader appropriate to this
2137         // combination of texture, entity, light source, and fogging, only use the
2138         // minimum features necessary to avoid wasting rendering time in the
2139         // fragment shader on features that are not being used
2140         unsigned int permutation = 0;
2141         unsigned int mode = 0;
2142         int blendfuncflags;
2143         static float dummy_colormod[3] = {1, 1, 1};
2144         float *colormod = rsurface.colormod;
2145         float m16f[16];
2146         matrix4x4_t tempmatrix;
2147         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2148         if (r_trippy.integer && !notrippy)
2149                 permutation |= SHADERPERMUTATION_TRIPPY;
2150         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2151                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2152         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2153                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2154         if (rsurfacepass == RSURFPASS_BACKGROUND)
2155         {
2156                 // distorted background
2157                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2158                 {
2159                         mode = SHADERMODE_WATER;
2160                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2161                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2162                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2163                         {
2164                                 // this is the right thing to do for wateralpha
2165                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2166                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2167                         }
2168                         else
2169                         {
2170                                 // this is the right thing to do for entity alpha
2171                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2173                         }
2174                 }
2175                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2176                 {
2177                         mode = SHADERMODE_REFRACTION;
2178                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2179                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2180                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2181                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2182                 }
2183                 else
2184                 {
2185                         mode = SHADERMODE_GENERIC;
2186                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2187                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2188                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2189                 }
2190                 if (vid.allowalphatocoverage)
2191                         GL_AlphaToCoverage(false);
2192         }
2193         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2194         {
2195                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2196                 {
2197                         switch(rsurface.texture->offsetmapping)
2198                         {
2199                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_OFF: break;
2203                         }
2204                 }
2205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207                 // normalmap (deferred prepass), may use alpha test on diffuse
2208                 mode = SHADERMODE_DEFERREDGEOMETRY;
2209                 GL_BlendFunc(GL_ONE, GL_ZERO);
2210                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2211                 if (vid.allowalphatocoverage)
2212                         GL_AlphaToCoverage(false);
2213         }
2214         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2215         {
2216                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2217                 {
2218                         switch(rsurface.texture->offsetmapping)
2219                         {
2220                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2221                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2223                         case OFFSETMAPPING_OFF: break;
2224                         }
2225                 }
2226                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2227                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2228                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2229                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2230                 // light source
2231                 mode = SHADERMODE_LIGHTSOURCE;
2232                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2233                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2234                 if (diffusescale > 0)
2235                         permutation |= SHADERPERMUTATION_DIFFUSE;
2236                 if (specularscale > 0)
2237                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2238                 if (r_refdef.fogenabled)
2239                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2240                 if (rsurface.texture->colormapping)
2241                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2242                 if (r_shadow_usingshadowmap2d)
2243                 {
2244                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2245                         if(r_shadow_shadowmapvsdct)
2246                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2247
2248                         if (r_shadow_shadowmap2ddepthbuffer)
2249                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2250                 }
2251                 if (rsurface.texture->reflectmasktexture)
2252                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2253                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2254                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2255                 if (vid.allowalphatocoverage)
2256                         GL_AlphaToCoverage(false);
2257         }
2258         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2259         {
2260                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2261                 {
2262                         switch(rsurface.texture->offsetmapping)
2263                         {
2264                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2265                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2267                         case OFFSETMAPPING_OFF: break;
2268                         }
2269                 }
2270                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2271                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2273                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2274                 // unshaded geometry (fullbright or ambient model lighting)
2275                 mode = SHADERMODE_FLATCOLOR;
2276                 ambientscale = diffusescale = specularscale = 0;
2277                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2278                         permutation |= SHADERPERMUTATION_GLOW;
2279                 if (r_refdef.fogenabled)
2280                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2281                 if (rsurface.texture->colormapping)
2282                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2283                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2284                 {
2285                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2286                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2287
2288                         if (r_shadow_shadowmap2ddepthbuffer)
2289                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2290                 }
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2292                         permutation |= SHADERPERMUTATION_REFLECTION;
2293                 if (rsurface.texture->reflectmasktexture)
2294                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2295                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2296                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297                 // when using alphatocoverage, we don't need alphakill
2298                 if (vid.allowalphatocoverage)
2299                 {
2300                         if (r_transparent_alphatocoverage.integer)
2301                         {
2302                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2303                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2304                         }
2305                         else
2306                                 GL_AlphaToCoverage(false);
2307                 }
2308         }
2309         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2310         {
2311                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2312                 {
2313                         switch(rsurface.texture->offsetmapping)
2314                         {
2315                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2316                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2318                         case OFFSETMAPPING_OFF: break;
2319                         }
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2324                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2325                 // directional model lighting
2326                 mode = SHADERMODE_LIGHTDIRECTION;
2327                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2328                         permutation |= SHADERPERMUTATION_GLOW;
2329                 permutation |= SHADERPERMUTATION_DIFFUSE;
2330                 if (specularscale > 0)
2331                         permutation |= SHADERPERMUTATION_SPECULAR;
2332                 if (r_refdef.fogenabled)
2333                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334                 if (rsurface.texture->colormapping)
2335                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2336                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2337                 {
2338                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2340
2341                         if (r_shadow_shadowmap2ddepthbuffer)
2342                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345                         permutation |= SHADERPERMUTATION_REFLECTION;
2346                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2347                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2348                 if (rsurface.texture->reflectmasktexture)
2349                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2350                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2351                 {
2352                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2353                         if (r_shadow_bouncegriddirectional)
2354                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2355                 }
2356                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2358                 // when using alphatocoverage, we don't need alphakill
2359                 if (vid.allowalphatocoverage)
2360                 {
2361                         if (r_transparent_alphatocoverage.integer)
2362                         {
2363                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2364                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2365                         }
2366                         else
2367                                 GL_AlphaToCoverage(false);
2368                 }
2369         }
2370         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2371         {
2372                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2373                 {
2374                         switch(rsurface.texture->offsetmapping)
2375                         {
2376                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2377                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379                         case OFFSETMAPPING_OFF: break;
2380                         }
2381                 }
2382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2383                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2385                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2386                 // ambient model lighting
2387                 mode = SHADERMODE_LIGHTDIRECTION;
2388                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2389                         permutation |= SHADERPERMUTATION_GLOW;
2390                 if (r_refdef.fogenabled)
2391                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2392                 if (rsurface.texture->colormapping)
2393                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2394                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2395                 {
2396                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2397                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2398
2399                         if (r_shadow_shadowmap2ddepthbuffer)
2400                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2401                 }
2402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2403                         permutation |= SHADERPERMUTATION_REFLECTION;
2404                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2405                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2406                 if (rsurface.texture->reflectmasktexture)
2407                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2408                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2409                 {
2410                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2411                         if (r_shadow_bouncegriddirectional)
2412                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413                 }
2414                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416                 // when using alphatocoverage, we don't need alphakill
2417                 if (vid.allowalphatocoverage)
2418                 {
2419                         if (r_transparent_alphatocoverage.integer)
2420                         {
2421                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2422                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2423                         }
2424                         else
2425                                 GL_AlphaToCoverage(false);
2426                 }
2427         }
2428         else
2429         {
2430                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2431                 {
2432                         switch(rsurface.texture->offsetmapping)
2433                         {
2434                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2435                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2437                         case OFFSETMAPPING_OFF: break;
2438                         }
2439                 }
2440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2441                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2442                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2443                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2444                 // lightmapped wall
2445                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2446                         permutation |= SHADERPERMUTATION_GLOW;
2447                 if (r_refdef.fogenabled)
2448                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2449                 if (rsurface.texture->colormapping)
2450                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2451                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2452                 {
2453                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2454                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2455
2456                         if (r_shadow_shadowmap2ddepthbuffer)
2457                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2460                         permutation |= SHADERPERMUTATION_REFLECTION;
2461                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2462                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2463                 if (rsurface.texture->reflectmasktexture)
2464                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2465                 if (FAKELIGHT_ENABLED)
2466                 {
2467                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2468                         mode = SHADERMODE_FAKELIGHT;
2469                         permutation |= SHADERPERMUTATION_DIFFUSE;
2470                         if (specularscale > 0)
2471                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472                 }
2473                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2474                 {
2475                         // deluxemapping (light direction texture)
2476                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2478                         else
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2480                         permutation |= SHADERPERMUTATION_DIFFUSE;
2481                         if (specularscale > 0)
2482                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483                 }
2484                 else if (r_glsl_deluxemapping.integer >= 2)
2485                 {
2486                         // fake deluxemapping (uniform light direction in tangentspace)
2487                         if (rsurface.uselightmaptexture)
2488                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2489                         else
2490                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2491                         permutation |= SHADERPERMUTATION_DIFFUSE;
2492                         if (specularscale > 0)
2493                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2494                 }
2495                 else if (rsurface.uselightmaptexture)
2496                 {
2497                         // ordinary lightmapping (q1bsp, q3bsp)
2498                         mode = SHADERMODE_LIGHTMAP;
2499                 }
2500                 else
2501                 {
2502                         // ordinary vertex coloring (q3bsp)
2503                         mode = SHADERMODE_VERTEXCOLOR;
2504                 }
2505                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2506                 {
2507                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2508                         if (r_shadow_bouncegriddirectional)
2509                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2510                 }
2511                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2513                 // when using alphatocoverage, we don't need alphakill
2514                 if (vid.allowalphatocoverage)
2515                 {
2516                         if (r_transparent_alphatocoverage.integer)
2517                         {
2518                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2519                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2520                         }
2521                         else
2522                                 GL_AlphaToCoverage(false);
2523                 }
2524         }
2525         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2526                 colormod = dummy_colormod;
2527         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2528                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2529         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2530                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2531         switch(vid.renderpath)
2532         {
2533         case RENDERPATH_D3D9:
2534 #ifdef SUPPORTD3D
2535                 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);
2536                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2537                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2538                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2539                 if (mode == SHADERMODE_LIGHTSOURCE)
2540                 {
2541                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2542                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2543                 }
2544                 else
2545                 {
2546                         if (mode == SHADERMODE_LIGHTDIRECTION)
2547                         {
2548                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2549                         }
2550                 }
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2553                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2554                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2555                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2556
2557                 if (mode == SHADERMODE_LIGHTSOURCE)
2558                 {
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2564
2565                         // additive passes are only darkened by fog, not tinted
2566                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2567                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2568                 }
2569                 else
2570                 {
2571                         if (mode == SHADERMODE_FLATCOLOR)
2572                         {
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2574                         }
2575                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2576                         {
2577                                 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]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2579                                 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);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2584                         }
2585                         else
2586                         {
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2589                                 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);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2592                         }
2593                         // additive passes are only darkened by fog, not tinted
2594                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2596                         else
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2598                         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);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2605                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2606                         if (mode == SHADERMODE_WATER)
2607                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2608                 }
2609                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2610                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2611                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2612                 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));
2613                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2614                 if (rsurface.texture->pantstexture)
2615                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2616                 else
2617                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2618                 if (rsurface.texture->shirttexture)
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2620                 else
2621                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2622                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2625                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2626                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2627                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2628                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2630                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2631                         );
2632                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2633                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2634                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2635                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2636
2637                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2638                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2639                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2640                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2645                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2646                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2647                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2648                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2649                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2650                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2651                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2652                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2653                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2654                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2655                 {
2656                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2657                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2658                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2659                 }
2660                 else
2661                 {
2662                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2663                 }
2664 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2666                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2667                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2668                 {
2669                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2670                         if (rsurface.rtlight)
2671                         {
2672                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2673                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2674                         }
2675                 }
2676 #endif
2677                 break;
2678         case RENDERPATH_D3D10:
2679                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2680                 break;
2681         case RENDERPATH_D3D11:
2682                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2683                 break;
2684         case RENDERPATH_GL20:
2685         case RENDERPATH_GLES2:
2686                 if (!vid.useinterleavedarrays)
2687                 {
2688                         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);
2689                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2690                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2696                 }
2697                 else
2698                 {
2699                         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);
2700                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2701                 }
2702                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2703                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2704                 if (mode == SHADERMODE_LIGHTSOURCE)
2705                 {
2706                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2707                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2708                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2709                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2710                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2711                         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);
2712         
2713                         // additive passes are only darkened by fog, not tinted
2714                         if (r_glsl_permutation->loc_FogColor >= 0)
2715                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2716                         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);
2717                 }
2718                 else
2719                 {
2720                         if (mode == SHADERMODE_FLATCOLOR)
2721                         {
2722                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2723                         }
2724                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2725                         {
2726                                 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]);
2727                                 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]);
2728                                 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);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2730                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2731                                 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]);
2732                                 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]);
2733                         }
2734                         else
2735                         {
2736                                 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]);
2737                                 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]);
2738                                 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);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2740                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2741                         }
2742                         // additive passes are only darkened by fog, not tinted
2743                         if (r_glsl_permutation->loc_FogColor >= 0)
2744                         {
2745                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2746                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2747                                 else
2748                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2749                         }
2750                         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);
2751                         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]);
2752                         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]);
2753                         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]);
2754                         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]);
2755                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2756                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2757                         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);
2758                         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]);
2759                 }
2760                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2762                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2763                 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]);
2764                 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]);
2765
2766                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2767                 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));
2768                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2769                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2770                 {
2771                         if (rsurface.texture->pantstexture)
2772                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2773                         else
2774                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2775                 }
2776                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2777                 {
2778                         if (rsurface.texture->shirttexture)
2779                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2780                         else
2781                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2782                 }
2783                 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]);
2784                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2785                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2786                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2787                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2788                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2789                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2791                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2792                         );
2793                 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);
2794                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2795                 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]);
2796                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2797                 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);}
2798                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2799
2800                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2801                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2802                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2803                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2804                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2805                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2806                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2811                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2812                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2813                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2814                 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);
2815                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2816                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2817                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2818                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2819                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2820                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2821                 {
2822                         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);
2823                         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);
2824                         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);
2825                 }
2826                 else
2827                 {
2828                         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);
2829                 }
2830                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2831                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2832                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2833                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2834                 {
2835                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2836                         if (rsurface.rtlight)
2837                         {
2838                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2839                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2840                         }
2841                 }
2842                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2843                 CHECKGLERROR
2844                 break;
2845         case RENDERPATH_GL11:
2846         case RENDERPATH_GL13:
2847         case RENDERPATH_GLES1:
2848                 break;
2849         case RENDERPATH_SOFT:
2850                 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);
2851                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2852                 R_SetupShader_SetPermutationSoft(mode, permutation);
2853                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2854                 if (mode == SHADERMODE_LIGHTSOURCE)
2855                 {
2856                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2862         
2863                         // additive passes are only darkened by fog, not tinted
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2865                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2866                 }
2867                 else
2868                 {
2869                         if (mode == SHADERMODE_FLATCOLOR)
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2872                         }
2873                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2874                         {
2875                                 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]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2877                                 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);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2880                                 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]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2882                         }
2883                         else
2884                         {
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2887                                 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);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2890                         }
2891                         // additive passes are only darkened by fog, not tinted
2892                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2894                         else
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2896                         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);
2897                         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]);
2898                         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]);
2899                         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]);
2900                         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]);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2903                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2904                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2905                 }
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2908                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2910                 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]);
2911
2912                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2913                 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));
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916                 {
2917                         if (rsurface.texture->pantstexture)
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2919                         else
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921                 }
2922                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923                 {
2924                         if (rsurface.texture->shirttexture)
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2926                         else
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928                 }
2929                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2934                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2935                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938                         );
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2943
2944                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2945                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2946                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2947                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2956                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2957                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2958                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2959                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2960                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2961                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2962                 {
2963                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2964                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2965                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966                 }
2967                 else
2968                 {
2969                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2970                 }
2971 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2974                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2975                 {
2976                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2977                         if (rsurface.rtlight)
2978                         {
2979                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2980                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2981                         }
2982                 }
2983                 break;
2984         }
2985 }
2986
2987 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2988 {
2989         // select a permutation of the lighting shader appropriate to this
2990         // combination of texture, entity, light source, and fogging, only use the
2991         // minimum features necessary to avoid wasting rendering time in the
2992         // fragment shader on features that are not being used
2993         unsigned int permutation = 0;
2994         unsigned int mode = 0;
2995         const float *lightcolorbase = rtlight->currentcolor;
2996         float ambientscale = rtlight->ambientscale;
2997         float diffusescale = rtlight->diffusescale;
2998         float specularscale = rtlight->specularscale;
2999         // this is the location of the light in view space
3000         vec3_t viewlightorigin;
3001         // this transforms from view space (camera) to light space (cubemap)
3002         matrix4x4_t viewtolight;
3003         matrix4x4_t lighttoview;
3004         float viewtolight16f[16];
3005         // light source
3006         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3007         if (rtlight->currentcubemap != r_texture_whitecube)
3008                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3009         if (diffusescale > 0)
3010                 permutation |= SHADERPERMUTATION_DIFFUSE;
3011         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3012                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3013         if (r_shadow_usingshadowmap2d)
3014         {
3015                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3016                 if (r_shadow_shadowmapvsdct)
3017                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018
3019                 if (r_shadow_shadowmap2ddepthbuffer)
3020                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3021         }
3022         if (vid.allowalphatocoverage)
3023                 GL_AlphaToCoverage(false);
3024         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3025         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3026         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3027         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3028         switch(vid.renderpath)
3029         {
3030         case RENDERPATH_D3D9:
3031 #ifdef SUPPORTD3D
3032                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3033                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3034                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3038                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3039                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3040                 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);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3043
3044                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3045                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3046                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3047                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3048                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3049 #endif
3050                 break;
3051         case RENDERPATH_D3D10:
3052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053                 break;
3054         case RENDERPATH_D3D11:
3055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056                 break;
3057         case RENDERPATH_GL20:
3058         case RENDERPATH_GLES2:
3059                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3062                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065                 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]);
3066                 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]);
3067                 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);
3068                 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]);
3069                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3070
3071                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3072                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3074                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3075                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3076                 break;
3077         case RENDERPATH_GL11:
3078         case RENDERPATH_GL13:
3079         case RENDERPATH_GLES1:
3080                 break;
3081         case RENDERPATH_SOFT:
3082                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3089                 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]);
3090                 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);
3091                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3093
3094                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3095                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3096                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3097                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3098                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3099                 break;
3100         }
3101 }
3102
3103 #define SKINFRAME_HASH 1024
3104
3105 typedef struct
3106 {
3107         int loadsequence; // incremented each level change
3108         memexpandablearray_t array;
3109         skinframe_t *hash[SKINFRAME_HASH];
3110 }
3111 r_skinframe_t;
3112 r_skinframe_t r_skinframe;
3113
3114 void R_SkinFrame_PrepareForPurge(void)
3115 {
3116         r_skinframe.loadsequence++;
3117         // wrap it without hitting zero
3118         if (r_skinframe.loadsequence >= 200)
3119                 r_skinframe.loadsequence = 1;
3120 }
3121
3122 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3123 {
3124         if (!skinframe)
3125                 return;
3126         // mark the skinframe as used for the purging code
3127         skinframe->loadsequence = r_skinframe.loadsequence;
3128 }
3129
3130 void R_SkinFrame_Purge(void)
3131 {
3132         int i;
3133         skinframe_t *s;
3134         for (i = 0;i < SKINFRAME_HASH;i++)
3135         {
3136                 for (s = r_skinframe.hash[i];s;s = s->next)
3137                 {
3138                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3139                         {
3140                                 if (s->merged == s->base)
3141                                         s->merged = NULL;
3142                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3143                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3144                                 R_PurgeTexture(s->merged);s->merged = NULL;
3145                                 R_PurgeTexture(s->base  );s->base   = NULL;
3146                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3147                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3148                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3149                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3150                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3151                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3152                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3153                                 s->loadsequence = 0;
3154                         }
3155                 }
3156         }
3157 }
3158
3159 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3160         skinframe_t *item;
3161         char basename[MAX_QPATH];
3162
3163         Image_StripImageExtension(name, basename, sizeof(basename));
3164
3165         if( last == NULL ) {
3166                 int hashindex;
3167                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3168                 item = r_skinframe.hash[hashindex];
3169         } else {
3170                 item = last->next;
3171         }
3172
3173         // linearly search through the hash bucket
3174         for( ; item ; item = item->next ) {
3175                 if( !strcmp( item->basename, basename ) ) {
3176                         return item;
3177                 }
3178         }
3179         return NULL;
3180 }
3181
3182 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3183 {
3184         skinframe_t *item;
3185         int hashindex;
3186         char basename[MAX_QPATH];
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3191         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3192                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3193                         break;
3194
3195         if (!item) {
3196                 rtexture_t *dyntexture;
3197                 // check whether its a dynamic texture
3198                 dyntexture = CL_GetDynTexture( basename );
3199                 if (!add && !dyntexture)
3200                         return NULL;
3201                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3202                 memset(item, 0, sizeof(*item));
3203                 strlcpy(item->basename, basename, sizeof(item->basename));
3204                 item->base = dyntexture; // either NULL or dyntexture handle
3205                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3206                 item->comparewidth = comparewidth;
3207                 item->compareheight = compareheight;
3208                 item->comparecrc = comparecrc;
3209                 item->next = r_skinframe.hash[hashindex];
3210                 r_skinframe.hash[hashindex] = item;
3211         }
3212         else if (textureflags & TEXF_FORCE_RELOAD)
3213         {
3214                 rtexture_t *dyntexture;
3215                 // check whether its a dynamic texture
3216                 dyntexture = CL_GetDynTexture( basename );
3217                 if (!add && !dyntexture)
3218                         return NULL;
3219                 if (item->merged == item->base)
3220                         item->merged = NULL;
3221                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3222                 R_PurgeTexture(item->stain );item->stain  = NULL;
3223                 R_PurgeTexture(item->merged);item->merged = NULL;
3224                 R_PurgeTexture(item->base  );item->base   = NULL;
3225                 R_PurgeTexture(item->pants );item->pants  = NULL;
3226                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3227                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3228                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3229                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3230                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3231         R_PurgeTexture(item->reflect);item->reflect = NULL;
3232                 item->loadsequence = 0;
3233         }
3234         else if( item->base == NULL )
3235         {
3236                 rtexture_t *dyntexture;
3237                 // check whether its a dynamic texture
3238                 // 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]
3239                 dyntexture = CL_GetDynTexture( basename );
3240                 item->base = dyntexture; // either NULL or dyntexture handle
3241         }
3242
3243         R_SkinFrame_MarkUsed(item);
3244         return item;
3245 }
3246
3247 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3248         { \
3249                 unsigned long long avgcolor[5], wsum; \
3250                 int pix, comp, w; \
3251                 avgcolor[0] = 0; \
3252                 avgcolor[1] = 0; \
3253                 avgcolor[2] = 0; \
3254                 avgcolor[3] = 0; \
3255                 avgcolor[4] = 0; \
3256                 wsum = 0; \
3257                 for(pix = 0; pix < cnt; ++pix) \
3258                 { \
3259                         w = 0; \
3260                         for(comp = 0; comp < 3; ++comp) \
3261                                 w += getpixel; \
3262                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3263                         { \
3264                                 ++wsum; \
3265                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3266                                 w = getpixel; \
3267                                 for(comp = 0; comp < 3; ++comp) \
3268                                         avgcolor[comp] += getpixel * w; \
3269                                 avgcolor[3] += w; \
3270                         } \
3271                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3272                         avgcolor[4] += getpixel; \
3273                 } \
3274                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3275                         avgcolor[3] = 1; \
3276                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3277                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3278                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3279                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3280         }
3281
3282 extern cvar_t gl_picmip;
3283 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3284 {
3285         int j;
3286         unsigned char *pixels;
3287         unsigned char *bumppixels;
3288         unsigned char *basepixels = NULL;
3289         int basepixels_width = 0;
3290         int basepixels_height = 0;
3291         skinframe_t *skinframe;
3292         rtexture_t *ddsbase = NULL;
3293         qboolean ddshasalpha = false;
3294         float ddsavgcolor[4];
3295         char basename[MAX_QPATH];
3296         int miplevel = R_PicmipForFlags(textureflags);
3297         int savemiplevel = miplevel;
3298         int mymiplevel;
3299         char vabuf[1024];
3300
3301         if (cls.state == ca_dedicated)
3302                 return NULL;
3303
3304         // return an existing skinframe if already loaded
3305         // if loading of the first image fails, don't make a new skinframe as it
3306         // would cause all future lookups of this to be missing
3307         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3308         if (skinframe && skinframe->base)
3309                 return skinframe;
3310
3311         Image_StripImageExtension(name, basename, sizeof(basename));
3312
3313         // check for DDS texture file first
3314         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3315         {
3316                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3317                 if (basepixels == NULL)
3318                         return NULL;
3319         }
3320
3321         // FIXME handle miplevel
3322
3323         if (developer_loading.integer)
3324                 Con_Printf("loading skin \"%s\"\n", name);
3325
3326         // we've got some pixels to store, so really allocate this new texture now
3327         if (!skinframe)
3328                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3329         textureflags &= ~TEXF_FORCE_RELOAD;
3330         skinframe->stain = NULL;
3331         skinframe->merged = NULL;
3332         skinframe->base = NULL;
3333         skinframe->pants = NULL;
3334         skinframe->shirt = NULL;
3335         skinframe->nmap = NULL;
3336         skinframe->gloss = NULL;
3337         skinframe->glow = NULL;
3338         skinframe->fog = NULL;
3339         skinframe->reflect = NULL;
3340         skinframe->hasalpha = false;
3341
3342         if (ddsbase)
3343         {
3344                 skinframe->base = ddsbase;
3345                 skinframe->hasalpha = ddshasalpha;
3346                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3347                 if (r_loadfog && skinframe->hasalpha)
3348                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3349                 //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]);
3350         }
3351         else
3352         {
3353                 basepixels_width = image_width;
3354                 basepixels_height = image_height;
3355                 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);
3356                 if (textureflags & TEXF_ALPHA)
3357                 {
3358                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3359                         {
3360                                 if (basepixels[j] < 255)
3361                                 {
3362                                         skinframe->hasalpha = true;
3363                                         break;
3364                                 }
3365                         }
3366                         if (r_loadfog && skinframe->hasalpha)
3367                         {
3368                                 // has transparent pixels
3369                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3370                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3371                                 {
3372                                         pixels[j+0] = 255;
3373                                         pixels[j+1] = 255;
3374                                         pixels[j+2] = 255;
3375                                         pixels[j+3] = basepixels[j+3];
3376                                 }
3377                                 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);
3378                                 Mem_Free(pixels);
3379                         }
3380                 }
3381                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3382 #ifndef USE_GLES2
3383                 //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]);
3384                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3385                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3386                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3387                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3388 #endif
3389         }
3390
3391         if (r_loaddds)
3392         {
3393                 mymiplevel = savemiplevel;
3394                 if (r_loadnormalmap)
3395                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3396                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3397                 if (r_loadgloss)
3398                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3399                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3400                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3401                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3402         }
3403
3404         // _norm is the name used by tenebrae and has been adopted as standard
3405         if (r_loadnormalmap && skinframe->nmap == NULL)
3406         {
3407                 mymiplevel = savemiplevel;
3408                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3409                 {
3410                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3411                         Mem_Free(pixels);
3412                         pixels = NULL;
3413                 }
3414                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3415                 {
3416                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3417                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3418                         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);
3419                         Mem_Free(pixels);
3420                         Mem_Free(bumppixels);
3421                 }
3422                 else if (r_shadow_bumpscale_basetexture.value > 0)
3423                 {
3424                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3425                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3426                         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);
3427                         Mem_Free(pixels);
3428                 }
3429 #ifndef USE_GLES2
3430                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3431                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3432 #endif
3433         }
3434
3435         // _luma is supported only for tenebrae compatibility
3436         // _glow is the preferred name
3437         mymiplevel = savemiplevel;
3438         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))))
3439         {
3440                 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);
3441 #ifndef USE_GLES2
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3443                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3444 #endif
3445                 Mem_Free(pixels);pixels = NULL;
3446         }
3447
3448         mymiplevel = savemiplevel;
3449         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3450         {
3451                 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);
3452 #ifndef USE_GLES2
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3454                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 #endif
3456                 Mem_Free(pixels);
3457                 pixels = NULL;
3458         }
3459
3460         mymiplevel = savemiplevel;
3461         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3462         {
3463                 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);
3464 #ifndef USE_GLES2
3465                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3466                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3467 #endif
3468                 Mem_Free(pixels);
3469                 pixels = NULL;
3470         }
3471
3472         mymiplevel = savemiplevel;
3473         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3474         {
3475                 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);
3476 #ifndef USE_GLES2
3477                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3478                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3479 #endif
3480                 Mem_Free(pixels);
3481                 pixels = NULL;
3482         }
3483
3484         mymiplevel = savemiplevel;
3485         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3486         {
3487                 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);
3488 #ifndef USE_GLES2
3489                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3490                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3491 #endif
3492                 Mem_Free(pixels);
3493                 pixels = NULL;
3494         }
3495
3496         if (basepixels)
3497                 Mem_Free(basepixels);
3498
3499         return skinframe;
3500 }
3501
3502 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3503 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3504 {
3505         int i;
3506         unsigned char *temp1, *temp2;
3507         skinframe_t *skinframe;
3508         char vabuf[1024];
3509
3510         if (cls.state == ca_dedicated)
3511                 return NULL;
3512
3513         // if already loaded just return it, otherwise make a new skinframe
3514         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3515         if (skinframe->base)
3516                 return skinframe;
3517         textureflags &= ~TEXF_FORCE_RELOAD;
3518
3519         skinframe->stain = NULL;
3520         skinframe->merged = NULL;
3521         skinframe->base = NULL;
3522         skinframe->pants = NULL;
3523         skinframe->shirt = NULL;
3524         skinframe->nmap = NULL;
3525         skinframe->gloss = NULL;
3526         skinframe->glow = NULL;
3527         skinframe->fog = NULL;
3528         skinframe->reflect = NULL;
3529         skinframe->hasalpha = false;
3530
3531         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3532         if (!skindata)
3533                 return NULL;
3534
3535         if (developer_loading.integer)
3536                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3537
3538         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3539         {
3540                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3541                 temp2 = temp1 + width * height * 4;
3542                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3543                 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);
3544                 Mem_Free(temp1);
3545         }
3546         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3547         if (textureflags & TEXF_ALPHA)
3548         {
3549                 for (i = 3;i < width * height * 4;i += 4)
3550                 {
3551                         if (skindata[i] < 255)
3552                         {
3553                                 skinframe->hasalpha = true;
3554                                 break;
3555                         }
3556                 }
3557                 if (r_loadfog && skinframe->hasalpha)
3558                 {
3559                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3560                         memcpy(fogpixels, skindata, width * height * 4);
3561                         for (i = 0;i < width * height * 4;i += 4)
3562                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3563                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3564                         Mem_Free(fogpixels);
3565                 }
3566         }
3567
3568         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3569         //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]);
3570
3571         return skinframe;
3572 }
3573
3574 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3575 {
3576         int i;
3577         int featuresmask;
3578         skinframe_t *skinframe;
3579
3580         if (cls.state == ca_dedicated)
3581                 return NULL;
3582
3583         // if already loaded just return it, otherwise make a new skinframe
3584         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3585         if (skinframe->base)
3586                 return skinframe;
3587         //textureflags &= ~TEXF_FORCE_RELOAD;
3588
3589         skinframe->stain = NULL;
3590         skinframe->merged = NULL;
3591         skinframe->base = NULL;
3592         skinframe->pants = NULL;
3593         skinframe->shirt = NULL;
3594         skinframe->nmap = NULL;
3595         skinframe->gloss = NULL;
3596         skinframe->glow = NULL;
3597         skinframe->fog = NULL;
3598         skinframe->reflect = NULL;
3599         skinframe->hasalpha = false;
3600
3601         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3602         if (!skindata)
3603                 return NULL;
3604
3605         if (developer_loading.integer)
3606                 Con_Printf("loading quake skin \"%s\"\n", name);
3607
3608         // 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)
3609         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3610         memcpy(skinframe->qpixels, skindata, width*height);
3611         skinframe->qwidth = width;
3612         skinframe->qheight = height;
3613
3614         featuresmask = 0;
3615         for (i = 0;i < width * height;i++)
3616                 featuresmask |= palette_featureflags[skindata[i]];
3617
3618         skinframe->hasalpha = false;
3619         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3620         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3621         skinframe->qgeneratemerged = true;
3622         skinframe->qgeneratebase = skinframe->qhascolormapping;
3623         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3624
3625         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3626         //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]);
3627
3628         return skinframe;
3629 }
3630
3631 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3632 {
3633         int width;
3634         int height;
3635         unsigned char *skindata;
3636         char vabuf[1024];
3637
3638         if (!skinframe->qpixels)
3639                 return;
3640
3641         if (!skinframe->qhascolormapping)
3642                 colormapped = false;
3643
3644         if (colormapped)
3645         {
3646                 if (!skinframe->qgeneratebase)
3647                         return;
3648         }
3649         else
3650         {
3651                 if (!skinframe->qgeneratemerged)
3652                         return;
3653         }
3654
3655         width = skinframe->qwidth;
3656         height = skinframe->qheight;
3657         skindata = skinframe->qpixels;
3658
3659         if (skinframe->qgeneratenmap)
3660         {
3661                 unsigned char *temp1, *temp2;
3662                 skinframe->qgeneratenmap = false;
3663                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3664                 temp2 = temp1 + width * height * 4;
3665                 // use either a custom palette or the quake palette
3666                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3667                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3668                 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);
3669                 Mem_Free(temp1);
3670         }
3671
3672         if (skinframe->qgenerateglow)
3673         {
3674                 skinframe->qgenerateglow = false;
3675                 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
3676         }
3677
3678         if (colormapped)
3679         {
3680                 skinframe->qgeneratebase = false;
3681                 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);
3682                 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);
3683                 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);
3684         }
3685         else
3686         {
3687                 skinframe->qgeneratemerged = false;
3688                 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);
3689         }
3690
3691         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3692         {
3693                 Mem_Free(skinframe->qpixels);
3694                 skinframe->qpixels = NULL;
3695         }
3696 }
3697
3698 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)
3699 {
3700         int i;
3701         skinframe_t *skinframe;
3702         char vabuf[1024];
3703
3704         if (cls.state == ca_dedicated)
3705                 return NULL;
3706
3707         // if already loaded just return it, otherwise make a new skinframe
3708         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3709         if (skinframe->base)
3710                 return skinframe;
3711         textureflags &= ~TEXF_FORCE_RELOAD;
3712
3713         skinframe->stain = NULL;
3714         skinframe->merged = NULL;
3715         skinframe->base = NULL;
3716         skinframe->pants = NULL;
3717         skinframe->shirt = NULL;
3718         skinframe->nmap = NULL;
3719         skinframe->gloss = NULL;
3720         skinframe->glow = NULL;
3721         skinframe->fog = NULL;
3722         skinframe->reflect = NULL;
3723         skinframe->hasalpha = false;
3724
3725         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3726         if (!skindata)
3727                 return NULL;
3728
3729         if (developer_loading.integer)
3730                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3731
3732         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3733         if (textureflags & TEXF_ALPHA)
3734         {
3735                 for (i = 0;i < width * height;i++)
3736                 {
3737                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3738                         {
3739                                 skinframe->hasalpha = true;
3740                                 break;
3741                         }
3742                 }
3743                 if (r_loadfog && skinframe->hasalpha)
3744                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3745         }
3746
3747         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3748         //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]);
3749
3750         return skinframe;
3751 }
3752
3753 skinframe_t *R_SkinFrame_LoadMissing(void)
3754 {
3755         skinframe_t *skinframe;
3756
3757         if (cls.state == ca_dedicated)
3758                 return NULL;
3759
3760         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3761         skinframe->stain = NULL;
3762         skinframe->merged = NULL;
3763         skinframe->base = NULL;
3764         skinframe->pants = NULL;
3765         skinframe->shirt = NULL;
3766         skinframe->nmap = NULL;
3767         skinframe->gloss = NULL;
3768         skinframe->glow = NULL;
3769         skinframe->fog = NULL;
3770         skinframe->reflect = NULL;
3771         skinframe->hasalpha = false;
3772
3773         skinframe->avgcolor[0] = rand() / RAND_MAX;
3774         skinframe->avgcolor[1] = rand() / RAND_MAX;
3775         skinframe->avgcolor[2] = rand() / RAND_MAX;
3776         skinframe->avgcolor[3] = 1;
3777
3778         return skinframe;
3779 }
3780
3781 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3782 typedef struct suffixinfo_s
3783 {
3784         const char *suffix;
3785         qboolean flipx, flipy, flipdiagonal;
3786 }
3787 suffixinfo_t;
3788 static suffixinfo_t suffix[3][6] =
3789 {
3790         {
3791                 {"px",   false, false, false},
3792                 {"nx",   false, false, false},
3793                 {"py",   false, false, false},
3794                 {"ny",   false, false, false},
3795                 {"pz",   false, false, false},
3796                 {"nz",   false, false, false}
3797         },
3798         {
3799                 {"posx", false, false, false},
3800                 {"negx", false, false, false},
3801                 {"posy", false, false, false},
3802                 {"negy", false, false, false},
3803                 {"posz", false, false, false},
3804                 {"negz", false, false, false}
3805         },
3806         {
3807                 {"rt",    true, false,  true},
3808                 {"lf",   false,  true,  true},
3809                 {"ft",    true,  true, false},
3810                 {"bk",   false, false, false},
3811                 {"up",    true, false,  true},
3812                 {"dn",    true, false,  true}
3813         }
3814 };
3815
3816 static int componentorder[4] = {0, 1, 2, 3};
3817
3818 static rtexture_t *R_LoadCubemap(const char *basename)
3819 {
3820         int i, j, cubemapsize;
3821         unsigned char *cubemappixels, *image_buffer;
3822         rtexture_t *cubemaptexture;
3823         char name[256];
3824         // must start 0 so the first loadimagepixels has no requested width/height
3825         cubemapsize = 0;
3826         cubemappixels = NULL;
3827         cubemaptexture = NULL;
3828         // keep trying different suffix groups (posx, px, rt) until one loads
3829         for (j = 0;j < 3 && !cubemappixels;j++)
3830         {
3831                 // load the 6 images in the suffix group
3832                 for (i = 0;i < 6;i++)
3833                 {
3834                         // generate an image name based on the base and and suffix
3835                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3836                         // load it
3837                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3838                         {
3839                                 // an image loaded, make sure width and height are equal
3840                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3841                                 {
3842                                         // if this is the first image to load successfully, allocate the cubemap memory
3843                                         if (!cubemappixels && image_width >= 1)
3844                                         {
3845                                                 cubemapsize = image_width;
3846                                                 // note this clears to black, so unavailable sides are black
3847                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3848                                         }
3849                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3850                                         if (cubemappixels)
3851                                                 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);
3852                                 }
3853                                 else
3854                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3855                                 // free the image
3856                                 Mem_Free(image_buffer);
3857                         }
3858                 }
3859         }
3860         // if a cubemap loaded, upload it
3861         if (cubemappixels)
3862         {
3863                 if (developer_loading.integer)
3864                         Con_Printf("loading cubemap \"%s\"\n", basename);
3865
3866                 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);
3867                 Mem_Free(cubemappixels);
3868         }
3869         else
3870         {
3871                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3872                 if (developer_loading.integer)
3873                 {
3874                         Con_Printf("(tried tried images ");
3875                         for (j = 0;j < 3;j++)
3876                                 for (i = 0;i < 6;i++)
3877                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3878                         Con_Print(" and was unable to find any of them).\n");
3879                 }
3880         }
3881         return cubemaptexture;
3882 }
3883
3884 rtexture_t *R_GetCubemap(const char *basename)
3885 {
3886         int i;
3887         for (i = 0;i < r_texture_numcubemaps;i++)
3888                 if (r_texture_cubemaps[i] != NULL)
3889                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3890                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3891         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3892                 return r_texture_whitecube;
3893         r_texture_numcubemaps++;
3894         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3895         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3896         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3897         return r_texture_cubemaps[i]->texture;
3898 }
3899
3900 static void R_Main_FreeViewCache(void)
3901 {
3902         if (r_refdef.viewcache.entityvisible)
3903                 Mem_Free(r_refdef.viewcache.entityvisible);
3904         if (r_refdef.viewcache.world_pvsbits)
3905                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3906         if (r_refdef.viewcache.world_leafvisible)
3907                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3908         if (r_refdef.viewcache.world_surfacevisible)
3909                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3910         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3911 }
3912
3913 static void R_Main_ResizeViewCache(void)
3914 {
3915         int numentities = r_refdef.scene.numentities;
3916         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3917         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3918         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3919         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3920         if (r_refdef.viewcache.maxentities < numentities)
3921         {
3922                 r_refdef.viewcache.maxentities = numentities;
3923                 if (r_refdef.viewcache.entityvisible)
3924                         Mem_Free(r_refdef.viewcache.entityvisible);
3925                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3926         }
3927         if (r_refdef.viewcache.world_numclusters != numclusters)
3928         {
3929                 r_refdef.viewcache.world_numclusters = numclusters;
3930                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3931                 if (r_refdef.viewcache.world_pvsbits)
3932                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3933                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3934         }
3935         if (r_refdef.viewcache.world_numleafs != numleafs)
3936         {
3937                 r_refdef.viewcache.world_numleafs = numleafs;
3938                 if (r_refdef.viewcache.world_leafvisible)
3939                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3940                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3941         }
3942         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3943         {
3944                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3945                 if (r_refdef.viewcache.world_surfacevisible)
3946                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3947                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3948         }
3949 }
3950
3951 extern rtexture_t *loadingscreentexture;
3952 static void gl_main_start(void)
3953 {
3954         loadingscreentexture = NULL;
3955         r_texture_blanknormalmap = NULL;
3956         r_texture_white = NULL;
3957         r_texture_grey128 = NULL;
3958         r_texture_black = NULL;
3959         r_texture_whitecube = NULL;
3960         r_texture_normalizationcube = NULL;
3961         r_texture_fogattenuation = NULL;
3962         r_texture_fogheighttexture = NULL;
3963         r_texture_gammaramps = NULL;
3964         r_texture_numcubemaps = 0;
3965
3966         r_loaddds = r_texture_dds_load.integer != 0;
3967         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3968
3969         switch(vid.renderpath)
3970         {
3971         case RENDERPATH_GL20:
3972         case RENDERPATH_D3D9:
3973         case RENDERPATH_D3D10:
3974         case RENDERPATH_D3D11:
3975         case RENDERPATH_SOFT:
3976         case RENDERPATH_GLES2:
3977                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3978                 Cvar_SetValueQuick(&gl_combine, 1);
3979                 Cvar_SetValueQuick(&r_glsl, 1);
3980                 r_loadnormalmap = true;
3981                 r_loadgloss = true;
3982                 r_loadfog = false;
3983                 break;
3984         case RENDERPATH_GL13:
3985         case RENDERPATH_GLES1:
3986                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3987                 Cvar_SetValueQuick(&gl_combine, 1);
3988                 Cvar_SetValueQuick(&r_glsl, 0);
3989                 r_loadnormalmap = false;
3990                 r_loadgloss = false;
3991                 r_loadfog = true;
3992                 break;
3993         case RENDERPATH_GL11:
3994                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3995                 Cvar_SetValueQuick(&gl_combine, 0);
3996                 Cvar_SetValueQuick(&r_glsl, 0);
3997                 r_loadnormalmap = false;
3998                 r_loadgloss = false;
3999                 r_loadfog = true;
4000                 break;
4001         }
4002
4003         R_AnimCache_Free();
4004         R_FrameData_Reset();
4005
4006         r_numqueries = 0;
4007         r_maxqueries = 0;
4008         memset(r_queries, 0, sizeof(r_queries));
4009
4010         r_qwskincache = NULL;
4011         r_qwskincache_size = 0;
4012
4013         // due to caching of texture_t references, the collision cache must be reset
4014         Collision_Cache_Reset(true);
4015
4016         // set up r_skinframe loading system for textures
4017         memset(&r_skinframe, 0, sizeof(r_skinframe));
4018         r_skinframe.loadsequence = 1;
4019         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4020
4021         r_main_texturepool = R_AllocTexturePool();
4022         R_BuildBlankTextures();
4023         R_BuildNoTexture();
4024         if (vid.support.arb_texture_cube_map)
4025         {
4026                 R_BuildWhiteCube();
4027                 R_BuildNormalizationCube();
4028         }
4029         r_texture_fogattenuation = NULL;
4030         r_texture_fogheighttexture = NULL;
4031         r_texture_gammaramps = NULL;
4032         //r_texture_fogintensity = NULL;
4033         memset(&r_fb, 0, sizeof(r_fb));
4034         r_glsl_permutation = NULL;
4035         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4036         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4037         glslshaderstring = NULL;
4038 #ifdef SUPPORTD3D
4039         r_hlsl_permutation = NULL;
4040         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4041         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4042 #endif
4043         hlslshaderstring = NULL;
4044         memset(&r_svbsp, 0, sizeof (r_svbsp));
4045
4046         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4047         r_texture_numcubemaps = 0;
4048
4049         r_refdef.fogmasktable_density = 0;
4050 }
4051
4052 static void gl_main_shutdown(void)
4053 {
4054         R_AnimCache_Free();
4055         R_FrameData_Reset();
4056
4057         R_Main_FreeViewCache();
4058
4059         switch(vid.renderpath)
4060         {
4061         case RENDERPATH_GL11:
4062         case RENDERPATH_GL13:
4063         case RENDERPATH_GL20:
4064         case RENDERPATH_GLES1:
4065         case RENDERPATH_GLES2:
4066 #ifdef GL_SAMPLES_PASSED_ARB
4067                 if (r_maxqueries)
4068                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4069 #endif
4070                 break;
4071         case RENDERPATH_D3D9:
4072                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4073                 break;
4074         case RENDERPATH_D3D10:
4075                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4076                 break;
4077         case RENDERPATH_D3D11:
4078                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4079                 break;
4080         case RENDERPATH_SOFT:
4081                 break;
4082         }
4083
4084         r_numqueries = 0;
4085         r_maxqueries = 0;
4086         memset(r_queries, 0, sizeof(r_queries));
4087
4088         r_qwskincache = NULL;
4089         r_qwskincache_size = 0;
4090
4091         // clear out the r_skinframe state
4092         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4093         memset(&r_skinframe, 0, sizeof(r_skinframe));
4094
4095         if (r_svbsp.nodes)
4096                 Mem_Free(r_svbsp.nodes);
4097         memset(&r_svbsp, 0, sizeof (r_svbsp));
4098         R_FreeTexturePool(&r_main_texturepool);
4099         loadingscreentexture = NULL;
4100         r_texture_blanknormalmap = NULL;
4101         r_texture_white = NULL;
4102         r_texture_grey128 = NULL;
4103         r_texture_black = NULL;
4104         r_texture_whitecube = NULL;
4105         r_texture_normalizationcube = NULL;
4106         r_texture_fogattenuation = NULL;
4107         r_texture_fogheighttexture = NULL;
4108         r_texture_gammaramps = NULL;
4109         r_texture_numcubemaps = 0;
4110         //r_texture_fogintensity = NULL;
4111         memset(&r_fb, 0, sizeof(r_fb));
4112         R_GLSL_Restart_f();
4113
4114         r_glsl_permutation = NULL;
4115         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4116         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4117         glslshaderstring = NULL;
4118 #ifdef SUPPORTD3D
4119         r_hlsl_permutation = NULL;
4120         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4121         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4122 #endif
4123         hlslshaderstring = NULL;
4124 }
4125
4126 static void gl_main_newmap(void)
4127 {
4128         // FIXME: move this code to client
4129         char *entities, entname[MAX_QPATH];
4130         if (r_qwskincache)
4131                 Mem_Free(r_qwskincache);
4132         r_qwskincache = NULL;
4133         r_qwskincache_size = 0;
4134         if (cl.worldmodel)
4135         {
4136                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4137                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4138                 {
4139                         CL_ParseEntityLump(entities);
4140                         Mem_Free(entities);
4141                         return;
4142                 }
4143                 if (cl.worldmodel->brush.entities)
4144                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4145         }
4146         R_Main_FreeViewCache();
4147
4148         R_FrameData_Reset();
4149 }
4150
4151 void GL_Main_Init(void)
4152 {
4153         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4154
4155         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4156         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4157         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4158         if (gamemode == GAME_NEHAHRA)
4159         {
4160                 Cvar_RegisterVariable (&gl_fogenable);
4161                 Cvar_RegisterVariable (&gl_fogdensity);
4162                 Cvar_RegisterVariable (&gl_fogred);
4163                 Cvar_RegisterVariable (&gl_foggreen);
4164                 Cvar_RegisterVariable (&gl_fogblue);
4165                 Cvar_RegisterVariable (&gl_fogstart);
4166                 Cvar_RegisterVariable (&gl_fogend);
4167                 Cvar_RegisterVariable (&gl_skyclip);
4168         }
4169         Cvar_RegisterVariable(&r_motionblur);
4170         Cvar_RegisterVariable(&r_damageblur);
4171         Cvar_RegisterVariable(&r_motionblur_averaging);
4172         Cvar_RegisterVariable(&r_motionblur_randomize);
4173         Cvar_RegisterVariable(&r_motionblur_minblur);
4174         Cvar_RegisterVariable(&r_motionblur_maxblur);
4175         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4176         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4177         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4178         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4179         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4180         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4181         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4182         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4183         Cvar_RegisterVariable(&r_equalize_entities_by);
4184         Cvar_RegisterVariable(&r_equalize_entities_to);
4185         Cvar_RegisterVariable(&r_depthfirst);
4186         Cvar_RegisterVariable(&r_useinfinitefarclip);
4187         Cvar_RegisterVariable(&r_farclip_base);
4188         Cvar_RegisterVariable(&r_farclip_world);
4189         Cvar_RegisterVariable(&r_nearclip);
4190         Cvar_RegisterVariable(&r_deformvertexes);
4191         Cvar_RegisterVariable(&r_transparent);
4192         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4193         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4194         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4195         Cvar_RegisterVariable(&r_showoverdraw);
4196         Cvar_RegisterVariable(&r_showbboxes);
4197         Cvar_RegisterVariable(&r_showsurfaces);
4198         Cvar_RegisterVariable(&r_showtris);
4199         Cvar_RegisterVariable(&r_shownormals);
4200         Cvar_RegisterVariable(&r_showlighting);
4201         Cvar_RegisterVariable(&r_showshadowvolumes);
4202         Cvar_RegisterVariable(&r_showcollisionbrushes);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4204         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4205         Cvar_RegisterVariable(&r_showdisabledepthtest);
4206         Cvar_RegisterVariable(&r_drawportals);
4207         Cvar_RegisterVariable(&r_drawentities);
4208         Cvar_RegisterVariable(&r_draw2d);
4209         Cvar_RegisterVariable(&r_drawworld);
4210         Cvar_RegisterVariable(&r_cullentities_trace);
4211         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4212         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4213         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4214         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4215         Cvar_RegisterVariable(&r_sortentities);
4216         Cvar_RegisterVariable(&r_drawviewmodel);
4217         Cvar_RegisterVariable(&r_drawexteriormodel);
4218         Cvar_RegisterVariable(&r_speeds);
4219         Cvar_RegisterVariable(&r_fullbrights);
4220         Cvar_RegisterVariable(&r_wateralpha);
4221         Cvar_RegisterVariable(&r_dynamic);
4222         Cvar_RegisterVariable(&r_fakelight);
4223         Cvar_RegisterVariable(&r_fakelight_intensity);
4224         Cvar_RegisterVariable(&r_fullbright);
4225         Cvar_RegisterVariable(&r_shadows);
4226         Cvar_RegisterVariable(&r_shadows_darken);
4227         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4228         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4229         Cvar_RegisterVariable(&r_shadows_throwdistance);
4230         Cvar_RegisterVariable(&r_shadows_throwdirection);
4231         Cvar_RegisterVariable(&r_shadows_focus);
4232         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4233         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4234         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4235         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4236         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4237         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4238         Cvar_RegisterVariable(&r_fog_exp2);
4239         Cvar_RegisterVariable(&r_fog_clear);
4240         Cvar_RegisterVariable(&r_drawfog);
4241         Cvar_RegisterVariable(&r_transparentdepthmasking);
4242         Cvar_RegisterVariable(&r_transparent_sortmindist);
4243         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4244         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4245         Cvar_RegisterVariable(&r_texture_dds_load);
4246         Cvar_RegisterVariable(&r_texture_dds_save);
4247         Cvar_RegisterVariable(&r_textureunits);
4248         Cvar_RegisterVariable(&gl_combine);
4249         Cvar_RegisterVariable(&r_usedepthtextures);
4250         Cvar_RegisterVariable(&r_viewfbo);
4251         Cvar_RegisterVariable(&r_viewscale);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4257         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4258         Cvar_RegisterVariable(&r_glsl);
4259         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4267         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4268         Cvar_RegisterVariable(&r_glsl_postprocess);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4276         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4277         Cvar_RegisterVariable(&r_celshading);
4278         Cvar_RegisterVariable(&r_celoutlines);
4279
4280         Cvar_RegisterVariable(&r_water);
4281         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4282         Cvar_RegisterVariable(&r_water_clippingplanebias);
4283         Cvar_RegisterVariable(&r_water_refractdistort);
4284         Cvar_RegisterVariable(&r_water_reflectdistort);
4285         Cvar_RegisterVariable(&r_water_scissormode);
4286         Cvar_RegisterVariable(&r_water_lowquality);
4287         Cvar_RegisterVariable(&r_water_hideplayer);
4288         Cvar_RegisterVariable(&r_water_fbo);
4289
4290         Cvar_RegisterVariable(&r_lerpsprites);
4291         Cvar_RegisterVariable(&r_lerpmodels);
4292         Cvar_RegisterVariable(&r_lerplightstyles);
4293         Cvar_RegisterVariable(&r_waterscroll);
4294         Cvar_RegisterVariable(&r_bloom);
4295         Cvar_RegisterVariable(&r_bloom_colorscale);
4296         Cvar_RegisterVariable(&r_bloom_brighten);
4297         Cvar_RegisterVariable(&r_bloom_blur);
4298         Cvar_RegisterVariable(&r_bloom_resolution);
4299         Cvar_RegisterVariable(&r_bloom_colorexponent);
4300         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4301         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4302         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4303         Cvar_RegisterVariable(&r_hdr_glowintensity);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4310         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4311         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4312         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4313         Cvar_RegisterVariable(&developer_texturelogging);
4314         Cvar_RegisterVariable(&gl_lightmaps);
4315         Cvar_RegisterVariable(&r_test);
4316         Cvar_RegisterVariable(&r_glsl_saturation);
4317         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4318         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4319         Cvar_RegisterVariable(&r_framedatasize);
4320         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4321                 Cvar_SetValue("r_fullbrights", 0);
4322         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4323 }
4324
4325 void Render_Init(void)
4326 {
4327         gl_backend_init();
4328         R_Textures_Init();
4329         GL_Main_Init();
4330         Font_Init();
4331         GL_Draw_Init();
4332         R_Shadow_Init();
4333         R_Sky_Init();
4334         GL_Surf_Init();
4335         Sbar_Init();
4336         R_Particles_Init();
4337         R_Explosion_Init();
4338         R_LightningBeams_Init();
4339         Mod_RenderInit();
4340 }
4341
4342 /*
4343 ===============
4344 GL_Init
4345 ===============
4346 */
4347 #ifndef USE_GLES2
4348 extern char *ENGINE_EXTENSIONS;
4349 void GL_Init (void)
4350 {
4351         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4352         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4353         gl_version = (const char *)qglGetString(GL_VERSION);
4354         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4355
4356         if (!gl_extensions)
4357                 gl_extensions = "";
4358         if (!gl_platformextensions)
4359                 gl_platformextensions = "";
4360
4361         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4362         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4363         Con_Printf("GL_VERSION: %s\n", gl_version);
4364         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4365         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4366
4367         VID_CheckExtensions();
4368
4369         // LordHavoc: report supported extensions
4370         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4371
4372         // clear to black (loading plaque will be seen over this)
4373         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4374 }
4375 #endif
4376
4377 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4378 {
4379         int i;
4380         mplane_t *p;
4381         if (r_trippy.integer)
4382                 return false;
4383         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4384         {
4385                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4386                 if (i == 4)
4387                         continue;
4388                 p = r_refdef.view.frustum + i;
4389                 switch(p->signbits)
4390                 {
4391                 default:
4392                 case 0:
4393                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4394                                 return true;
4395                         break;
4396                 case 1:
4397                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4398                                 return true;
4399                         break;
4400                 case 2:
4401                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4402                                 return true;
4403                         break;
4404                 case 3:
4405                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4406                                 return true;
4407                         break;
4408                 case 4:
4409                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4410                                 return true;
4411                         break;
4412                 case 5:
4413                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4414                                 return true;
4415                         break;
4416                 case 6:
4417                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4418                                 return true;
4419                         break;
4420                 case 7:
4421                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4422                                 return true;
4423                         break;
4424                 }
4425         }
4426         return false;
4427 }
4428
4429 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4430 {
4431         int i;
4432         const mplane_t *p;
4433         if (r_trippy.integer)
4434                 return false;
4435         for (i = 0;i < numplanes;i++)
4436         {
4437                 p = planes + i;
4438                 switch(p->signbits)
4439                 {
4440                 default:
4441                 case 0:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 1:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 2:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 3:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 4:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 5:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 case 6:
4466                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4467                                 return true;
4468                         break;
4469                 case 7:
4470                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4471                                 return true;
4472                         break;
4473                 }
4474         }
4475         return false;
4476 }
4477
4478 //==================================================================================
4479
4480 // LordHavoc: this stores temporary data used within the same frame
4481
4482 typedef struct r_framedata_mem_s
4483 {
4484         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4485         size_t size; // how much usable space
4486         size_t current; // how much space in use
4487         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4488         size_t wantedsize; // how much space was allocated
4489         unsigned char *data; // start of real data (16byte aligned)
4490 }
4491 r_framedata_mem_t;
4492
4493 static r_framedata_mem_t *r_framedata_mem;
4494
4495 void R_FrameData_Reset(void)
4496 {
4497         while (r_framedata_mem)
4498         {
4499                 r_framedata_mem_t *next = r_framedata_mem->purge;
4500                 Mem_Free(r_framedata_mem);
4501                 r_framedata_mem = next;
4502         }
4503 }
4504
4505 static void R_FrameData_Resize(void)
4506 {
4507         size_t wantedsize;
4508         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4509         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4510         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4511         {
4512                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4513                 newmem->wantedsize = wantedsize;
4514                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4515                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4516                 newmem->current = 0;
4517                 newmem->mark = 0;
4518                 newmem->purge = r_framedata_mem;
4519                 r_framedata_mem = newmem;
4520         }
4521 }
4522
4523 void R_FrameData_NewFrame(void)
4524 {
4525         R_FrameData_Resize();
4526         if (!r_framedata_mem)
4527                 return;
4528         // if we ran out of space on the last frame, free the old memory now
4529         while (r_framedata_mem->purge)
4530         {
4531                 // repeatedly remove the second item in the list, leaving only head
4532                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4533                 Mem_Free(r_framedata_mem->purge);
4534                 r_framedata_mem->purge = next;
4535         }
4536         // reset the current mem pointer
4537         r_framedata_mem->current = 0;
4538         r_framedata_mem->mark = 0;
4539 }
4540
4541 void *R_FrameData_Alloc(size_t size)
4542 {
4543         void *data;
4544
4545         // align to 16 byte boundary - the data pointer is already aligned, so we
4546         // only need to ensure the size of every allocation is also aligned
4547         size = (size + 15) & ~15;
4548
4549         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4550         {
4551                 // emergency - we ran out of space, allocate more memory
4552                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4553                 R_FrameData_Resize();
4554         }
4555
4556         data = r_framedata_mem->data + r_framedata_mem->current;
4557         r_framedata_mem->current += size;
4558
4559         // count the usage for stats
4560         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4561         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4562
4563         return (void *)data;
4564 }
4565
4566 void *R_FrameData_Store(size_t size, void *data)
4567 {
4568         void *d = R_FrameData_Alloc(size);
4569         if (d && data)
4570                 memcpy(d, data, size);
4571         return d;
4572 }
4573
4574 void R_FrameData_SetMark(void)
4575 {
4576         if (!r_framedata_mem)
4577                 return;
4578         r_framedata_mem->mark = r_framedata_mem->current;
4579 }
4580
4581 void R_FrameData_ReturnToMark(void)
4582 {
4583         if (!r_framedata_mem)
4584                 return;
4585         r_framedata_mem->current = r_framedata_mem->mark;
4586 }
4587
4588 //==================================================================================
4589
4590 // LordHavoc: animcache originally written by Echon, rewritten since then
4591
4592 /**
4593  * Animation cache prevents re-generating mesh data for an animated model
4594  * multiple times in one frame for lighting, shadowing, reflections, etc.
4595  */
4596
4597 void R_AnimCache_Free(void)
4598 {
4599 }
4600
4601 void R_AnimCache_ClearCache(void)
4602 {
4603         int i;
4604         entity_render_t *ent;
4605
4606         for (i = 0;i < r_refdef.scene.numentities;i++)
4607         {
4608                 ent = r_refdef.scene.entities[i];
4609                 ent->animcache_vertex3f = NULL;
4610                 ent->animcache_normal3f = NULL;
4611                 ent->animcache_svector3f = NULL;
4612                 ent->animcache_tvector3f = NULL;
4613                 ent->animcache_vertexmesh = NULL;
4614                 ent->animcache_vertex3fbuffer = NULL;
4615                 ent->animcache_vertexmeshbuffer = NULL;
4616         }
4617 }
4618
4619 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4620 {
4621         int i;
4622
4623         // check if we need the meshbuffers
4624         if (!vid.useinterleavedarrays)
4625                 return;
4626
4627         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4628                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4629         // TODO: upload vertex3f buffer?
4630         if (ent->animcache_vertexmesh)
4631         {
4632                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4633                 for (i = 0;i < numvertices;i++)
4634                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4635                 if (ent->animcache_svector3f)
4636                         for (i = 0;i < numvertices;i++)
4637                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4638                 if (ent->animcache_tvector3f)
4639                         for (i = 0;i < numvertices;i++)
4640                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4641                 if (ent->animcache_normal3f)
4642                         for (i = 0;i < numvertices;i++)
4643                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4644                 // TODO: upload vertexmeshbuffer?
4645         }
4646 }
4647
4648 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4649 {
4650         dp_model_t *model = ent->model;
4651         int numvertices;
4652         // see if it's already cached this frame
4653         if (ent->animcache_vertex3f)
4654         {
4655                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4656                 if (wantnormals || wanttangents)
4657                 {
4658                         if (ent->animcache_normal3f)
4659                                 wantnormals = false;
4660                         if (ent->animcache_svector3f)
4661                                 wanttangents = false;
4662                         if (wantnormals || wanttangents)
4663                         {
4664                                 numvertices = model->surfmesh.num_vertices;
4665                                 if (wantnormals)
4666                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4667                                 if (wanttangents)
4668                                 {
4669                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4670                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671                                 }
4672                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4673                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4674                         }
4675                 }
4676         }
4677         else
4678         {
4679                 // see if this ent is worth caching
4680                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4681                         return false;
4682                 // get some memory for this entity and generate mesh data
4683                 numvertices = model->surfmesh.num_vertices;
4684                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4685                 if (wantnormals)
4686                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4687                 if (wanttangents)
4688                 {
4689                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4690                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4691                 }
4692                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4693                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4694         }
4695         return true;
4696 }
4697
4698 void R_AnimCache_CacheVisibleEntities(void)
4699 {
4700         int i;
4701         qboolean wantnormals = true;
4702         qboolean wanttangents = !r_showsurfaces.integer;
4703
4704         switch(vid.renderpath)
4705         {
4706         case RENDERPATH_GL20:
4707         case RENDERPATH_D3D9:
4708         case RENDERPATH_D3D10:
4709         case RENDERPATH_D3D11:
4710         case RENDERPATH_GLES2:
4711                 break;
4712         case RENDERPATH_GL11:
4713         case RENDERPATH_GL13:
4714         case RENDERPATH_GLES1:
4715                 wanttangents = false;
4716                 break;
4717         case RENDERPATH_SOFT:
4718                 break;
4719         }
4720
4721         if (r_shownormals.integer)
4722                 wanttangents = wantnormals = true;
4723
4724         // TODO: thread this
4725         // NOTE: R_PrepareRTLights() also caches entities
4726
4727         for (i = 0;i < r_refdef.scene.numentities;i++)
4728                 if (r_refdef.viewcache.entityvisible[i])
4729                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4730 }
4731
4732 //==================================================================================
4733
4734 extern cvar_t r_overheadsprites_pushback;
4735
4736 static void R_View_UpdateEntityLighting (void)
4737 {
4738         int i;
4739         entity_render_t *ent;
4740         vec3_t tempdiffusenormal, avg;
4741         vec_t f, fa, fd, fdd;
4742         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4743
4744         for (i = 0;i < r_refdef.scene.numentities;i++)
4745         {
4746                 ent = r_refdef.scene.entities[i];
4747
4748                 // skip unseen models
4749                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4750                         continue;
4751
4752                 // skip bsp models
4753                 if (ent->model && ent->model == cl.worldmodel)
4754                 {
4755                         // TODO: use modellight for r_ambient settings on world?
4756                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4757                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4758                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4759                         continue;
4760                 }
4761                 
4762                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4763                 {
4764                         // aleady updated by CSQC
4765                         // TODO: force modellight on BSP models in this case?
4766                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4767                 }
4768                 else
4769                 {
4770                         // fetch the lighting from the worldmodel data
4771                         VectorClear(ent->modellight_ambient);
4772                         VectorClear(ent->modellight_diffuse);
4773                         VectorClear(tempdiffusenormal);
4774                         if (ent->flags & RENDER_LIGHT)
4775                         {
4776                                 vec3_t org;
4777                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4778
4779                                 // complete lightning for lit sprites
4780                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4781                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4782                                 {
4783                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4784                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4785                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4786                                 }
4787                                 else
4788                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4789
4790                                 if(ent->flags & RENDER_EQUALIZE)
4791                                 {
4792                                         // first fix up ambient lighting...
4793                                         if(r_equalize_entities_minambient.value > 0)
4794                                         {
4795                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4796                                                 if(fd > 0)
4797                                                 {
4798                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4799                                                         if(fa < r_equalize_entities_minambient.value * fd)
4800                                                         {
4801                                                                 // solve:
4802                                                                 //   fa'/fd' = minambient
4803                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4804                                                                 //   ...
4805                                                                 //   fa' = fd' * minambient
4806                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4807                                                                 //   ...
4808                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4809                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4810                                                                 //   ...
4811                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4812                                                                 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
4813                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4814                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4815                                                         }
4816                                                 }
4817                                         }
4818
4819                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4820                                         {
4821                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4822                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4823                                                 f = fa + 0.25 * fd;
4824                                                 if(f > 0)
4825                                                 {
4826                                                         // adjust brightness and saturation to target
4827                                                         avg[0] = avg[1] = avg[2] = fa / f;
4828                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4829                                                         avg[0] = avg[1] = avg[2] = fd / f;
4830                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4831                                                 }
4832                                         }
4833                                 }
4834                         }
4835                         else // highly rare
4836                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4837                 }
4838
4839                 // move the light direction into modelspace coordinates for lighting code
4840                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4841                 if(VectorLength2(ent->modellight_lightdir) == 0)
4842                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4843                 VectorNormalize(ent->modellight_lightdir);
4844         }
4845 }
4846
4847 #define MAX_LINEOFSIGHTTRACES 64
4848
4849 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4850 {
4851         int i;
4852         vec3_t boxmins, boxmaxs;
4853         vec3_t start;
4854         vec3_t end;
4855         dp_model_t *model = r_refdef.scene.worldmodel;
4856
4857         if (!model || !model->brush.TraceLineOfSight)
4858                 return true;
4859
4860         // expand the box a little
4861         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4862         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4863         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4864         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4865         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4866         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4867
4868         // return true if eye is inside enlarged box
4869         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4870                 return true;
4871
4872         // try center
4873         VectorCopy(eye, start);
4874         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4875         if (model->brush.TraceLineOfSight(model, start, end))
4876                 return true;
4877
4878         // try various random positions
4879         for (i = 0;i < numsamples;i++)
4880         {
4881                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4882                 if (model->brush.TraceLineOfSight(model, start, end))
4883                         return true;
4884         }
4885
4886         return false;
4887 }
4888
4889
4890 static void R_View_UpdateEntityVisible (void)
4891 {
4892         int i;
4893         int renderimask;
4894         int samples;
4895         entity_render_t *ent;
4896
4897         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4898                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4899                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4900                 :                                                          RENDER_EXTERIORMODEL;
4901         if (!r_drawviewmodel.integer)
4902                 renderimask |= RENDER_VIEWMODEL;
4903         if (!r_drawexteriormodel.integer)
4904                 renderimask |= RENDER_EXTERIORMODEL;
4905         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4906         {
4907                 // worldmodel can check visibility
4908                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4909                 for (i = 0;i < r_refdef.scene.numentities;i++)
4910                 {
4911                         ent = r_refdef.scene.entities[i];
4912                         if (!(ent->flags & renderimask))
4913                         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)))
4914                         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))
4915                                 r_refdef.viewcache.entityvisible[i] = true;
4916                 }
4917         }
4918         else
4919         {
4920                 // no worldmodel or it can't check visibility
4921                 for (i = 0;i < r_refdef.scene.numentities;i++)
4922                 {
4923                         ent = r_refdef.scene.entities[i];
4924                         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));
4925                 }
4926         }
4927         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4928                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4929         {
4930                 for (i = 0;i < r_refdef.scene.numentities;i++)
4931                 {
4932                         if (!r_refdef.viewcache.entityvisible[i])
4933                                 continue;
4934                         ent = r_refdef.scene.entities[i];
4935                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4936                         {
4937                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4938                                 if (samples < 0)
4939                                         continue; // temp entities do pvs only
4940                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4941                                         ent->last_trace_visibility = realtime;
4942                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4943                                         r_refdef.viewcache.entityvisible[i] = 0;
4944                         }
4945                 }
4946         }
4947 }
4948
4949 /// only used if skyrendermasked, and normally returns false
4950 static int R_DrawBrushModelsSky (void)
4951 {
4952         int i, sky;
4953         entity_render_t *ent;
4954
4955         sky = false;
4956         for (i = 0;i < r_refdef.scene.numentities;i++)
4957         {
4958                 if (!r_refdef.viewcache.entityvisible[i])
4959                         continue;
4960                 ent = r_refdef.scene.entities[i];
4961                 if (!ent->model || !ent->model->DrawSky)
4962                         continue;
4963                 ent->model->DrawSky(ent);
4964                 sky = true;
4965         }
4966         return sky;
4967 }
4968
4969 static void R_DrawNoModel(entity_render_t *ent);
4970 static void R_DrawModels(void)
4971 {
4972         int i;
4973         entity_render_t *ent;
4974
4975         for (i = 0;i < r_refdef.scene.numentities;i++)
4976         {
4977                 if (!r_refdef.viewcache.entityvisible[i])
4978                         continue;
4979                 ent = r_refdef.scene.entities[i];
4980                 r_refdef.stats.entities++;
4981                 /*
4982                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4983                 {
4984                         vec3_t f, l, u, o;
4985                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4986                         Con_Printf("R_DrawModels\n");
4987                         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]);
4988                         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);
4989                         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);
4990                 }
4991                 */
4992                 if (ent->model && ent->model->Draw != NULL)
4993                         ent->model->Draw(ent);
4994                 else
4995                         R_DrawNoModel(ent);
4996         }
4997 }
4998
4999 static void R_DrawModelsDepth(void)
5000 {
5001         int i;
5002         entity_render_t *ent;
5003
5004         for (i = 0;i < r_refdef.scene.numentities;i++)
5005         {
5006                 if (!r_refdef.viewcache.entityvisible[i])
5007                         continue;
5008                 ent = r_refdef.scene.entities[i];
5009                 if (ent->model && ent->model->DrawDepth != NULL)
5010                         ent->model->DrawDepth(ent);
5011         }
5012 }
5013
5014 static void R_DrawModelsDebug(void)
5015 {
5016         int i;
5017         entity_render_t *ent;
5018
5019         for (i = 0;i < r_refdef.scene.numentities;i++)
5020         {
5021                 if (!r_refdef.viewcache.entityvisible[i])
5022                         continue;
5023                 ent = r_refdef.scene.entities[i];
5024                 if (ent->model && ent->model->DrawDebug != NULL)
5025                         ent->model->DrawDebug(ent);
5026         }
5027 }
5028
5029 static void R_DrawModelsAddWaterPlanes(void)
5030 {
5031         int i;
5032         entity_render_t *ent;
5033
5034         for (i = 0;i < r_refdef.scene.numentities;i++)
5035         {
5036                 if (!r_refdef.viewcache.entityvisible[i])
5037                         continue;
5038                 ent = r_refdef.scene.entities[i];
5039                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5040                         ent->model->DrawAddWaterPlanes(ent);
5041         }
5042 }
5043
5044 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}};
5045
5046 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5047 {
5048         if (r_hdr_irisadaptation.integer)
5049         {
5050                 vec3_t p;
5051                 vec3_t ambient;
5052                 vec3_t diffuse;
5053                 vec3_t diffusenormal;
5054                 vec3_t forward;
5055                 vec_t brightness = 0.0f;
5056                 vec_t goal;
5057                 vec_t current;
5058                 vec_t d;
5059                 int c;
5060                 VectorCopy(r_refdef.view.forward, forward);
5061                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5062                 {
5063                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5064                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5065                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5066                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5067                         d = DotProduct(forward, diffusenormal);
5068                         brightness += VectorLength(ambient);
5069                         if (d > 0)
5070                                 brightness += d * VectorLength(diffuse);
5071                 }
5072                 brightness *= 1.0f / c;
5073                 brightness += 0.00001f; // make sure it's never zero
5074                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5075                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5076                 current = r_hdr_irisadaptation_value.value;
5077                 if (current < goal)
5078                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5079                 else if (current > goal)
5080                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5081                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5082                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5083         }
5084         else if (r_hdr_irisadaptation_value.value != 1.0f)
5085                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5086 }
5087
5088 static void R_View_SetFrustum(const int *scissor)
5089 {
5090         int i;
5091         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5092         vec3_t forward, left, up, origin, v;
5093
5094         if(scissor)
5095         {
5096                 // flipped x coordinates (because x points left here)
5097                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5098                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5099
5100                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5101                 switch(vid.renderpath)
5102                 {
5103                         case RENDERPATH_D3D9:
5104                         case RENDERPATH_D3D10:
5105                         case RENDERPATH_D3D11:
5106                                 // non-flipped y coordinates
5107                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5108                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5109                                 break;
5110                         case RENDERPATH_SOFT:
5111                         case RENDERPATH_GL11:
5112                         case RENDERPATH_GL13:
5113                         case RENDERPATH_GL20:
5114                         case RENDERPATH_GLES1:
5115                         case RENDERPATH_GLES2:
5116                                 // non-flipped y coordinates
5117                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5118                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5119                                 break;
5120                 }
5121         }
5122
5123         // we can't trust r_refdef.view.forward and friends in reflected scenes
5124         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5125
5126 #if 0
5127         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5128         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5129         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5130         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5131         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5132         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5133         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5134         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5135         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5136         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5137         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5138         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5139 #endif
5140
5141 #if 0
5142         zNear = r_refdef.nearclip;
5143         nudge = 1.0 - 1.0 / (1<<23);
5144         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5145         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5146         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5147         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5148         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5149         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5150         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5151         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5152 #endif
5153
5154
5155
5156 #if 0
5157         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5158         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5159         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5160         r_refdef.view.frustum[0].dist = m[15] - m[12];
5161
5162         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5163         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5164         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5165         r_refdef.view.frustum[1].dist = m[15] + m[12];
5166
5167         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5168         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5169         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5170         r_refdef.view.frustum[2].dist = m[15] - m[13];
5171
5172         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5173         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5174         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5175         r_refdef.view.frustum[3].dist = m[15] + m[13];
5176
5177         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5178         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5179         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5180         r_refdef.view.frustum[4].dist = m[15] - m[14];
5181
5182         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5183         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5184         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5185         r_refdef.view.frustum[5].dist = m[15] + m[14];
5186 #endif
5187
5188         if (r_refdef.view.useperspective)
5189         {
5190                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5191                 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]);
5192                 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]);
5193                 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]);
5194                 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]);
5195
5196                 // then the normals from the corners relative to origin
5197                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5198                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5199                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5200                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5201
5202                 // in a NORMAL view, forward cross left == up
5203                 // in a REFLECTED view, forward cross left == down
5204                 // so our cross products above need to be adjusted for a left handed coordinate system
5205                 CrossProduct(forward, left, v);
5206                 if(DotProduct(v, up) < 0)
5207                 {
5208                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5209                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5210                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5211                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5212                 }
5213
5214                 // Leaving those out was a mistake, those were in the old code, and they
5215                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5216                 // I couldn't reproduce it after adding those normalizations. --blub
5217                 VectorNormalize(r_refdef.view.frustum[0].normal);
5218                 VectorNormalize(r_refdef.view.frustum[1].normal);
5219                 VectorNormalize(r_refdef.view.frustum[2].normal);
5220                 VectorNormalize(r_refdef.view.frustum[3].normal);
5221
5222                 // make the corners absolute
5223                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5224                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5225                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5226                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5227
5228                 // one more normal
5229                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5230
5231                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5232                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5233                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5234                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5235                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5236         }
5237         else
5238         {
5239                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5240                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5241                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5242                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5243                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5244                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5245                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5246                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5247                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5248                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5249         }
5250         r_refdef.view.numfrustumplanes = 5;
5251
5252         if (r_refdef.view.useclipplane)
5253         {
5254                 r_refdef.view.numfrustumplanes = 6;
5255                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5256         }
5257
5258         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5259                 PlaneClassify(r_refdef.view.frustum + i);
5260
5261         // LordHavoc: note to all quake engine coders, Quake had a special case
5262         // for 90 degrees which assumed a square view (wrong), so I removed it,
5263         // Quake2 has it disabled as well.
5264
5265         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5266         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5267         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5268         //PlaneClassify(&frustum[0]);
5269
5270         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5271         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5272         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5273         //PlaneClassify(&frustum[1]);
5274
5275         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5276         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5277         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5278         //PlaneClassify(&frustum[2]);
5279
5280         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5281         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5282         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5283         //PlaneClassify(&frustum[3]);
5284
5285         // nearclip plane
5286         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5287         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5288         //PlaneClassify(&frustum[4]);
5289 }
5290
5291 static void R_View_UpdateWithScissor(const int *myscissor)
5292 {
5293         R_Main_ResizeViewCache();
5294         R_View_SetFrustum(myscissor);
5295         R_View_WorldVisibility(r_refdef.view.useclipplane);
5296         R_View_UpdateEntityVisible();
5297         R_View_UpdateEntityLighting();
5298 }
5299
5300 static void R_View_Update(void)
5301 {
5302         R_Main_ResizeViewCache();
5303         R_View_SetFrustum(NULL);
5304         R_View_WorldVisibility(r_refdef.view.useclipplane);
5305         R_View_UpdateEntityVisible();
5306         R_View_UpdateEntityLighting();
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                         R_AnimCache_CacheVisibleEntities();
5851                         if(r_water_scissormode.integer & 1)
5852                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5853                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5854
5855                         if (!p->fbo_reflection)
5856                                 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);
5857                         r_fb.water.hideplayer = false;
5858                 }
5859
5860                 // render the normal view scene and copy into texture
5861                 // (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)
5862                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5863                 {
5864                         r_refdef.view = myview;
5865                         if(r_water_scissormode.integer)
5866                         {
5867                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5868                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5869                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5870                         }
5871
5872                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5873
5874                         r_refdef.view.clipplane = p->plane;
5875                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5876                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5877
5878                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5879                         {
5880                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5881                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5882                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5883                                 R_RenderView_UpdateViewVectors();
5884                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5885                                 {
5886                                         r_refdef.view.usecustompvs = true;
5887                                         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);
5888                                 }
5889                         }
5890
5891                         PlaneClassify(&r_refdef.view.clipplane);
5892
5893                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5894                         R_ClearScreen(r_refdef.fogenabled);
5895                         if(r_water_scissormode.integer & 2)
5896                                 R_View_UpdateWithScissor(myscissor);
5897                         else
5898                                 R_View_Update();
5899                         R_AnimCache_CacheVisibleEntities();
5900                         if(r_water_scissormode.integer & 1)
5901                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5902                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5903
5904                         if (!p->fbo_refraction)
5905                                 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);
5906                         r_fb.water.hideplayer = false;
5907                 }
5908                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5909                 {
5910                         r_refdef.view = myview;
5911
5912                         r_refdef.view.clipplane = p->plane;
5913                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5914                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5915
5916                         r_refdef.view.width = r_fb.water.camerawidth;
5917                         r_refdef.view.height = r_fb.water.cameraheight;
5918                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5919                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5920                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5921                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5922
5923                         if(p->camera_entity)
5924                         {
5925                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5926                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5927                         }
5928
5929                         // note: all of the view is used for displaying... so
5930                         // there is no use in scissoring
5931
5932                         // reverse the cullface settings for this render
5933                         r_refdef.view.cullface_front = GL_FRONT;
5934                         r_refdef.view.cullface_back = GL_BACK;
5935                         // also reverse the view matrix
5936                         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
5937                         R_RenderView_UpdateViewVectors();
5938                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5939                         {
5940                                 r_refdef.view.usecustompvs = true;
5941                                 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);
5942                         }
5943                         
5944                         // camera needs no clipplane
5945                         r_refdef.view.useclipplane = false;
5946
5947                         PlaneClassify(&r_refdef.view.clipplane);
5948
5949                         r_fb.water.hideplayer = false;
5950
5951                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5952                         R_ClearScreen(r_refdef.fogenabled);
5953                         R_View_Update();
5954                         R_AnimCache_CacheVisibleEntities();
5955                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5956
5957                         if (!p->fbo_camera)
5958                                 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);
5959                         r_fb.water.hideplayer = false;
5960                 }
5961
5962         }
5963         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5964         r_fb.water.renderingscene = false;
5965         r_refdef.view = originalview;
5966         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5967         if (!r_fb.water.depthtexture)
5968                 R_ClearScreen(r_refdef.fogenabled);
5969         R_View_Update();
5970         R_AnimCache_CacheVisibleEntities();
5971         goto finish;
5972 error:
5973         r_refdef.view = originalview;
5974         r_fb.water.renderingscene = false;
5975         Cvar_SetValueQuick(&r_water, 0);
5976         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5977 finish:
5978         // lowquality hack, restore cvars
5979         if (qualityreduction > 0)
5980         {
5981                 if (qualityreduction >= 1)
5982                 {
5983                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5984                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5985                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5986                 }
5987                 if (qualityreduction >= 2)
5988                 {
5989                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5990                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5991                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5992                 }
5993         }
5994 }
5995
5996 static void R_Bloom_StartFrame(void)
5997 {
5998         int i;
5999         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6000         int viewwidth, viewheight;
6001         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6002         textype_t textype = TEXTYPE_COLORBUFFER;
6003
6004         switch (vid.renderpath)
6005         {
6006         case RENDERPATH_GL20:
6007                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6008                 if (vid.support.ext_framebuffer_object)
6009                 {
6010                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6011                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6012                 }
6013                 break;
6014         case RENDERPATH_GL11:
6015         case RENDERPATH_GL13:
6016         case RENDERPATH_GLES1:
6017         case RENDERPATH_GLES2:
6018         case RENDERPATH_D3D9:
6019         case RENDERPATH_D3D10:
6020         case RENDERPATH_D3D11:
6021                 r_fb.usedepthtextures = false;
6022                 break;
6023         case RENDERPATH_SOFT:
6024                 r_fb.usedepthtextures = true;
6025                 break;
6026         }
6027
6028         if (r_viewscale_fpsscaling.integer)
6029         {
6030                 double actualframetime;
6031                 double targetframetime;
6032                 double adjust;
6033                 actualframetime = r_refdef.lastdrawscreentime;
6034                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6035                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6036                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6037                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6038                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6039                 viewscalefpsadjusted += adjust;
6040                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6041         }
6042         else
6043                 viewscalefpsadjusted = 1.0f;
6044
6045         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6046
6047         switch(vid.renderpath)
6048         {
6049         case RENDERPATH_GL20:
6050         case RENDERPATH_D3D9:
6051         case RENDERPATH_D3D10:
6052         case RENDERPATH_D3D11:
6053         case RENDERPATH_SOFT:
6054         case RENDERPATH_GLES2:
6055                 break;
6056         case RENDERPATH_GL11:
6057         case RENDERPATH_GL13:
6058         case RENDERPATH_GLES1:
6059                 return;
6060         }
6061
6062         // set bloomwidth and bloomheight to the bloom resolution that will be
6063         // used (often less than the screen resolution for faster rendering)
6064         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6065         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6066         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6067         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6068         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6069
6070         // calculate desired texture sizes
6071         if (vid.support.arb_texture_non_power_of_two)
6072         {
6073                 screentexturewidth = vid.width;
6074                 screentextureheight = vid.height;
6075                 bloomtexturewidth = r_fb.bloomwidth;
6076                 bloomtextureheight = r_fb.bloomheight;
6077         }
6078         else
6079         {
6080                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6081                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6082                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6083                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6084         }
6085
6086         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))
6087         {
6088                 Cvar_SetValueQuick(&r_bloom, 0);
6089                 Cvar_SetValueQuick(&r_motionblur, 0);
6090                 Cvar_SetValueQuick(&r_damageblur, 0);
6091         }
6092
6093         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6094          && !r_bloom.integer
6095          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6096          && !useviewfbo
6097          && r_viewscale.value == 1.0f
6098          && !r_viewscale_fpsscaling.integer)
6099                 screentexturewidth = screentextureheight = 0;
6100         if (!r_bloom.integer)
6101                 bloomtexturewidth = bloomtextureheight = 0;
6102
6103         // allocate textures as needed
6104         if (r_fb.screentexturewidth != screentexturewidth
6105          || r_fb.screentextureheight != screentextureheight
6106          || r_fb.bloomtexturewidth != bloomtexturewidth
6107          || r_fb.bloomtextureheight != bloomtextureheight
6108          || r_fb.textype != textype
6109          || useviewfbo != (r_fb.fbo != 0))
6110         {
6111                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6112                 {
6113                         if (r_fb.bloomtexture[i])
6114                                 R_FreeTexture(r_fb.bloomtexture[i]);
6115                         r_fb.bloomtexture[i] = NULL;
6116
6117                         if (r_fb.bloomfbo[i])
6118                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6119                         r_fb.bloomfbo[i] = 0;
6120                 }
6121
6122                 if (r_fb.fbo)
6123                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6124                 r_fb.fbo = 0;
6125
6126                 if (r_fb.colortexture)
6127                         R_FreeTexture(r_fb.colortexture);
6128                 r_fb.colortexture = NULL;
6129
6130                 if (r_fb.depthtexture)
6131                         R_FreeTexture(r_fb.depthtexture);
6132                 r_fb.depthtexture = NULL;
6133
6134                 if (r_fb.ghosttexture)
6135                         R_FreeTexture(r_fb.ghosttexture);
6136                 r_fb.ghosttexture = NULL;
6137
6138                 r_fb.screentexturewidth = screentexturewidth;
6139                 r_fb.screentextureheight = screentextureheight;
6140                 r_fb.bloomtexturewidth = bloomtexturewidth;
6141                 r_fb.bloomtextureheight = bloomtextureheight;
6142                 r_fb.textype = textype;
6143
6144                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6145                 {
6146                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6147                                 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);
6148                         r_fb.ghosttexture_valid = false;
6149                         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);
6150                         if (useviewfbo)
6151                         {
6152                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6153                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6154                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6155                         }
6156                 }
6157
6158                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6159                 {
6160                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6161                         {
6162                                 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);
6163                                 if (useviewfbo)
6164                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6165                         }
6166                 }
6167         }
6168
6169         // bloom texture is a different resolution
6170         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6171         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6172         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6173         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6174         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6175
6176         // set up a texcoord array for the full resolution screen image
6177         // (we have to keep this around to copy back during final render)
6178         r_fb.screentexcoord2f[0] = 0;
6179         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6180         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6181         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6182         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6183         r_fb.screentexcoord2f[5] = 0;
6184         r_fb.screentexcoord2f[6] = 0;
6185         r_fb.screentexcoord2f[7] = 0;
6186
6187         if(r_fb.fbo) 
6188         {
6189                 for (i = 1;i < 8;i += 2)
6190                 {
6191                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6192                 }
6193         }
6194
6195         // set up a texcoord array for the reduced resolution bloom image
6196         // (which will be additive blended over the screen image)
6197         r_fb.bloomtexcoord2f[0] = 0;
6198         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6199         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6200         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6201         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6202         r_fb.bloomtexcoord2f[5] = 0;
6203         r_fb.bloomtexcoord2f[6] = 0;
6204         r_fb.bloomtexcoord2f[7] = 0;
6205
6206         switch(vid.renderpath)
6207         {
6208         case RENDERPATH_GL11:
6209         case RENDERPATH_GL13:
6210         case RENDERPATH_GL20:
6211         case RENDERPATH_SOFT:
6212         case RENDERPATH_GLES1:
6213         case RENDERPATH_GLES2:
6214                 break;
6215         case RENDERPATH_D3D9:
6216         case RENDERPATH_D3D10:
6217         case RENDERPATH_D3D11:
6218                 for (i = 0;i < 4;i++)
6219                 {
6220                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6221                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6222                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6223                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6224                 }
6225                 break;
6226         }
6227
6228         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6229
6230         if (r_fb.fbo)
6231                 r_refdef.view.clear = true;
6232 }
6233
6234 static void R_Bloom_MakeTexture(void)
6235 {
6236         int x, range, dir;
6237         float xoffset, yoffset, r, brighten;
6238         rtexture_t *intex;
6239         float colorscale = r_bloom_colorscale.value;
6240
6241         r_refdef.stats.bloom++;
6242     
6243 #if 0
6244     // this copy is unnecessary since it happens in R_BlendView already
6245         if (!r_fb.fbo)
6246         {
6247                 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);
6248                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6249         }
6250 #endif
6251
6252         // scale down screen texture to the bloom texture size
6253         CHECKGLERROR
6254         r_fb.bloomindex = 0;
6255         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6256         R_SetViewport(&r_fb.bloomviewport);
6257         GL_DepthTest(false);
6258         GL_BlendFunc(GL_ONE, GL_ZERO);
6259         GL_Color(colorscale, colorscale, colorscale, 1);
6260         // 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...
6261         switch(vid.renderpath)
6262         {
6263         case RENDERPATH_GL11:
6264         case RENDERPATH_GL13:
6265         case RENDERPATH_GL20:
6266         case RENDERPATH_GLES1:
6267         case RENDERPATH_GLES2:
6268         case RENDERPATH_SOFT:
6269                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6270                 break;
6271         case RENDERPATH_D3D9:
6272         case RENDERPATH_D3D10:
6273         case RENDERPATH_D3D11:
6274                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6275                 break;
6276         }
6277         // TODO: do boxfilter scale-down in shader?
6278         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6279         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6280         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6281
6282         // we now have a properly scaled bloom image
6283         if (!r_fb.bloomfbo[r_fb.bloomindex])
6284         {
6285                 // copy it into the bloom texture
6286                 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);
6287                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6288         }
6289
6290         // multiply bloom image by itself as many times as desired
6291         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6292         {
6293                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6294                 r_fb.bloomindex ^= 1;
6295                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6296                 x *= 2;
6297                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6298                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6299                 {
6300                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6301                         GL_Color(r,r,r,1); // apply fix factor
6302                 }
6303                 else
6304                 {
6305                         if(x <= 2)
6306                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6307                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6308                         GL_Color(1,1,1,1); // no fix factor supported here
6309                 }
6310                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6311                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6312                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6313                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6314
6315                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6316                 {
6317                         // copy the darkened image to a texture
6318                         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);
6319                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6320                 }
6321         }
6322
6323         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6324         brighten = r_bloom_brighten.value;
6325         brighten = sqrt(brighten);
6326         if(range >= 1)
6327                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6328
6329         for (dir = 0;dir < 2;dir++)
6330         {
6331                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6332                 r_fb.bloomindex ^= 1;
6333                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6334                 // blend on at multiple vertical offsets to achieve a vertical blur
6335                 // TODO: do offset blends using GLSL
6336                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6337                 GL_BlendFunc(GL_ONE, GL_ZERO);
6338                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6339                 for (x = -range;x <= range;x++)
6340                 {
6341                         if (!dir){xoffset = 0;yoffset = x;}
6342                         else {xoffset = x;yoffset = 0;}
6343                         xoffset /= (float)r_fb.bloomtexturewidth;
6344                         yoffset /= (float)r_fb.bloomtextureheight;
6345                         // compute a texcoord array with the specified x and y offset
6346                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6347                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6348                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6349                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6350                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6351                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6352                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6353                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6354                         // this r value looks like a 'dot' particle, fading sharply to
6355                         // black at the edges
6356                         // (probably not realistic but looks good enough)
6357                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6358                         //r = brighten/(range*2+1);
6359                         r = brighten / (range * 2 + 1);
6360                         if(range >= 1)
6361                                 r *= (1 - x*x/(float)(range*range));
6362                         GL_Color(r, r, r, 1);
6363                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6364                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6365                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6366                         GL_BlendFunc(GL_ONE, GL_ONE);
6367                 }
6368
6369                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6370                 {
6371                         // copy the vertically or horizontally blurred bloom view to a texture
6372                         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);
6373                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6374                 }
6375         }
6376 }
6377
6378 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6379 {
6380         unsigned int permutation;
6381         float uservecs[4][4];
6382
6383         R_EntityMatrix(&identitymatrix);
6384
6385         switch (vid.renderpath)
6386         {
6387         case RENDERPATH_GL20:
6388         case RENDERPATH_D3D9:
6389         case RENDERPATH_D3D10:
6390         case RENDERPATH_D3D11:
6391         case RENDERPATH_SOFT:
6392         case RENDERPATH_GLES2:
6393                 permutation =
6394                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6395                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6396                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6397                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6398                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6399
6400                 if (r_fb.colortexture)
6401                 {
6402                         if (!r_fb.fbo)
6403                         {
6404                                 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);
6405                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6406                         }
6407
6408                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6409                         {
6410                                 // declare variables
6411                                 float blur_factor, blur_mouseaccel, blur_velocity;
6412                                 static float blur_average; 
6413                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6414
6415                                 // set a goal for the factoring
6416                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6417                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6418                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6419                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6420                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6421                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6422
6423                                 // from the goal, pick an averaged value between goal and last value
6424                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6425                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6426
6427                                 // enforce minimum amount of blur 
6428                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6429
6430                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6431
6432                                 // calculate values into a standard alpha
6433                                 cl.motionbluralpha = 1 - exp(-
6434                                                 (
6435                                                  (r_motionblur.value * blur_factor / 80)
6436                                                  +
6437                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6438                                                 )
6439                                                 /
6440                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6441                                           );
6442
6443                                 // randomization for the blur value to combat persistent ghosting
6444                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6445                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6446
6447                                 // apply the blur
6448                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6449                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6450                                 {
6451                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6452                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6453                                         switch(vid.renderpath)
6454                                         {
6455                                         case RENDERPATH_GL11:
6456                                         case RENDERPATH_GL13:
6457                                         case RENDERPATH_GL20:
6458                                         case RENDERPATH_GLES1:
6459                                         case RENDERPATH_GLES2:
6460                                         case RENDERPATH_SOFT:
6461                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6462                                                 break;
6463                                         case RENDERPATH_D3D9:
6464                                         case RENDERPATH_D3D10:
6465                                         case RENDERPATH_D3D11:
6466                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6467                                                 break;
6468                                         }
6469                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6470                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6471                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6472                                 }
6473
6474                                 // updates old view angles for next pass
6475                                 VectorCopy(cl.viewangles, blur_oldangles);
6476
6477                                 // copy view into the ghost texture
6478                                 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);
6479                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6480                                 r_fb.ghosttexture_valid = true;
6481                         }
6482                 }
6483                 else
6484                 {
6485                         // no r_fb.colortexture means we're rendering to the real fb
6486                         // we may still have to do view tint...
6487                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6488                         {
6489                                 // apply a color tint to the whole view
6490                                 R_ResetViewRendering2D(0, NULL, NULL);
6491                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6492                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6493                                 R_SetupShader_Generic_NoTexture(false, true);
6494                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6495                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6496                         }
6497                         break; // no screen processing, no bloom, skip it
6498                 }
6499
6500                 if (r_fb.bloomtexture[0])
6501                 {
6502                         // make the bloom texture
6503                         R_Bloom_MakeTexture();
6504                 }
6505
6506 #if _MSC_VER >= 1400
6507 #define sscanf sscanf_s
6508 #endif
6509                 memset(uservecs, 0, sizeof(uservecs));
6510                 if (r_glsl_postprocess_uservec1_enable.integer)
6511                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6512                 if (r_glsl_postprocess_uservec2_enable.integer)
6513                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6514                 if (r_glsl_postprocess_uservec3_enable.integer)
6515                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6516                 if (r_glsl_postprocess_uservec4_enable.integer)
6517                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6518
6519                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6520                 GL_Color(1, 1, 1, 1);
6521                 GL_BlendFunc(GL_ONE, GL_ZERO);
6522
6523                 switch(vid.renderpath)
6524                 {
6525                 case RENDERPATH_GL20:
6526                 case RENDERPATH_GLES2:
6527                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6528                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6529                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6530                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6531                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6532                         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]);
6533                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6534                         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]);
6535                         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]);
6536                         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]);
6537                         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]);
6538                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6539                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6540                         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);
6541                         break;
6542                 case RENDERPATH_D3D9:
6543 #ifdef SUPPORTD3D
6544                         // 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...
6545                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6546                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6547                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6548                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6549                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6550                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6551                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6552                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6553                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6554                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6555                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6556                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6557                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6558                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6559 #endif
6560                         break;
6561                 case RENDERPATH_D3D10:
6562                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6563                         break;
6564                 case RENDERPATH_D3D11:
6565                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6566                         break;
6567                 case RENDERPATH_SOFT:
6568                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6569                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6570                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6571                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6572                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6573                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6574                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6577                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6578                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6579                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6580                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6581                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6582                         break;
6583                 default:
6584                         break;
6585                 }
6586                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6587                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6588                 break;
6589         case RENDERPATH_GL11:
6590         case RENDERPATH_GL13:
6591         case RENDERPATH_GLES1:
6592                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6593                 {
6594                         // apply a color tint to the whole view
6595                         R_ResetViewRendering2D(0, NULL, NULL);
6596                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6597                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6598                         R_SetupShader_Generic_NoTexture(false, true);
6599                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6600                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6601                 }
6602                 break;
6603         }
6604 }
6605
6606 matrix4x4_t r_waterscrollmatrix;
6607
6608 void R_UpdateFog(void)
6609 {
6610         // Nehahra fog
6611         if (gamemode == GAME_NEHAHRA)
6612         {
6613                 if (gl_fogenable.integer)
6614                 {
6615                         r_refdef.oldgl_fogenable = true;
6616                         r_refdef.fog_density = gl_fogdensity.value;
6617                         r_refdef.fog_red = gl_fogred.value;
6618                         r_refdef.fog_green = gl_foggreen.value;
6619                         r_refdef.fog_blue = gl_fogblue.value;
6620                         r_refdef.fog_alpha = 1;
6621                         r_refdef.fog_start = 0;
6622                         r_refdef.fog_end = gl_skyclip.value;
6623                         r_refdef.fog_height = 1<<30;
6624                         r_refdef.fog_fadedepth = 128;
6625                 }
6626                 else if (r_refdef.oldgl_fogenable)
6627                 {
6628                         r_refdef.oldgl_fogenable = false;
6629                         r_refdef.fog_density = 0;
6630                         r_refdef.fog_red = 0;
6631                         r_refdef.fog_green = 0;
6632                         r_refdef.fog_blue = 0;
6633                         r_refdef.fog_alpha = 0;
6634                         r_refdef.fog_start = 0;
6635                         r_refdef.fog_end = 0;
6636                         r_refdef.fog_height = 1<<30;
6637                         r_refdef.fog_fadedepth = 128;
6638                 }
6639         }
6640
6641         // fog parms
6642         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6643         r_refdef.fog_start = max(0, r_refdef.fog_start);
6644         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6645
6646         if (r_refdef.fog_density && r_drawfog.integer)
6647         {
6648                 r_refdef.fogenabled = true;
6649                 // this is the point where the fog reaches 0.9986 alpha, which we
6650                 // consider a good enough cutoff point for the texture
6651                 // (0.9986 * 256 == 255.6)
6652                 if (r_fog_exp2.integer)
6653                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6654                 else
6655                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6656                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6657                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6658                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6659                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6660                         R_BuildFogHeightTexture();
6661                 // fog color was already set
6662                 // update the fog texture
6663                 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)
6664                         R_BuildFogTexture();
6665                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6666                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6667         }
6668         else
6669                 r_refdef.fogenabled = false;
6670
6671         // fog color
6672         if (r_refdef.fog_density)
6673         {
6674                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6675                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6676                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6677
6678                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6679                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6680                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6681                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6682
6683                 {
6684                         vec3_t fogvec;
6685                         VectorCopy(r_refdef.fogcolor, fogvec);
6686                         //   color.rgb *= ContrastBoost * SceneBrightness;
6687                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6688                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6689                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6690                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6691                 }
6692         }
6693 }
6694
6695 void R_UpdateVariables(void)
6696 {
6697         R_Textures_Frame();
6698
6699         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6700
6701         r_refdef.farclip = r_farclip_base.value;
6702         if (r_refdef.scene.worldmodel)
6703                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6704         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6705
6706         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6707                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6708         r_refdef.polygonfactor = 0;
6709         r_refdef.polygonoffset = 0;
6710         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6711         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6712
6713         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6714         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6715         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6716         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6717         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6718         if (FAKELIGHT_ENABLED)
6719         {
6720                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6721         }
6722         else if (r_refdef.scene.worldmodel)
6723         {
6724                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6725         }
6726         if (r_showsurfaces.integer)
6727         {
6728                 r_refdef.scene.rtworld = false;
6729                 r_refdef.scene.rtworldshadows = false;
6730                 r_refdef.scene.rtdlight = false;
6731                 r_refdef.scene.rtdlightshadows = false;
6732                 r_refdef.lightmapintensity = 0;
6733         }
6734
6735         switch(vid.renderpath)
6736         {
6737         case RENDERPATH_GL20:
6738         case RENDERPATH_D3D9:
6739         case RENDERPATH_D3D10:
6740         case RENDERPATH_D3D11:
6741         case RENDERPATH_SOFT:
6742         case RENDERPATH_GLES2:
6743                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6744                 {
6745                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6746                         {
6747                                 // build GLSL gamma texture
6748 #define RAMPWIDTH 256
6749                                 unsigned short ramp[RAMPWIDTH * 3];
6750                                 unsigned char rampbgr[RAMPWIDTH][4];
6751                                 int i;
6752
6753                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6754
6755                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6756                                 for(i = 0; i < RAMPWIDTH; ++i)
6757                                 {
6758                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6759                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6760                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6761                                         rampbgr[i][3] = 0;
6762                                 }
6763                                 if (r_texture_gammaramps)
6764                                 {
6765                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6766                                 }
6767                                 else
6768                                 {
6769                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6770                                 }
6771                         }
6772                 }
6773                 else
6774                 {
6775                         // remove GLSL gamma texture
6776                 }
6777                 break;
6778         case RENDERPATH_GL11:
6779         case RENDERPATH_GL13:
6780         case RENDERPATH_GLES1:
6781                 break;
6782         }
6783 }
6784
6785 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6786 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6787 /*
6788 ================
6789 R_SelectScene
6790 ================
6791 */
6792 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6793         if( scenetype != r_currentscenetype ) {
6794                 // store the old scenetype
6795                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6796                 r_currentscenetype = scenetype;
6797                 // move in the new scene
6798                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6799         }
6800 }
6801
6802 /*
6803 ================
6804 R_GetScenePointer
6805 ================
6806 */
6807 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6808 {
6809         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6810         if( scenetype == r_currentscenetype ) {
6811                 return &r_refdef.scene;
6812         } else {
6813                 return &r_scenes_store[ scenetype ];
6814         }
6815 }
6816
6817 static int R_SortEntities_Compare(const void *ap, const void *bp)
6818 {
6819         const entity_render_t *a = *(const entity_render_t **)ap;
6820         const entity_render_t *b = *(const entity_render_t **)bp;
6821
6822         // 1. compare model
6823         if(a->model < b->model)
6824                 return -1;
6825         if(a->model > b->model)
6826                 return +1;
6827
6828         // 2. compare skin
6829         // TODO possibly calculate the REAL skinnum here first using
6830         // skinscenes?
6831         if(a->skinnum < b->skinnum)
6832                 return -1;
6833         if(a->skinnum > b->skinnum)
6834                 return +1;
6835
6836         // everything we compared is equal
6837         return 0;
6838 }
6839 static void R_SortEntities(void)
6840 {
6841         // below or equal 2 ents, sorting never gains anything
6842         if(r_refdef.scene.numentities <= 2)
6843                 return;
6844         // sort
6845         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6846 }
6847
6848 /*
6849 ================
6850 R_RenderView
6851 ================
6852 */
6853 int dpsoftrast_test;
6854 extern cvar_t r_shadow_bouncegrid;
6855 void R_RenderView(void)
6856 {
6857         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6858         int fbo;
6859         rtexture_t *depthtexture;
6860         rtexture_t *colortexture;
6861
6862         dpsoftrast_test = r_test.integer;
6863
6864         if (r_timereport_active)
6865                 R_TimeReport("start");
6866         r_textureframe++; // used only by R_GetCurrentTexture
6867         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6868
6869         if(R_CompileShader_CheckStaticParms())
6870                 R_GLSL_Restart_f();
6871
6872         if (!r_drawentities.integer)
6873                 r_refdef.scene.numentities = 0;
6874         else if (r_sortentities.integer)
6875                 R_SortEntities();
6876
6877         R_AnimCache_ClearCache();
6878         R_FrameData_NewFrame();
6879
6880         /* adjust for stereo display */
6881         if(R_Stereo_Active())
6882         {
6883                 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);
6884                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6885         }
6886
6887         if (r_refdef.view.isoverlay)
6888         {
6889                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6890                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6891                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6892                 R_TimeReport("depthclear");
6893
6894                 r_refdef.view.showdebug = false;
6895
6896                 r_fb.water.enabled = false;
6897                 r_fb.water.numwaterplanes = 0;
6898
6899                 R_RenderScene(0, NULL, NULL);
6900
6901                 r_refdef.view.matrix = originalmatrix;
6902
6903                 CHECKGLERROR
6904                 return;
6905         }
6906
6907         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6908         {
6909                 r_refdef.view.matrix = originalmatrix;
6910                 return;
6911         }
6912
6913         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6914
6915         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6916                 // in sRGB fallback, behave similar to true sRGB: convert this
6917                 // value from linear to sRGB
6918                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6919
6920         R_RenderView_UpdateViewVectors();
6921
6922         R_Shadow_UpdateWorldLightSelection();
6923
6924         R_Bloom_StartFrame();
6925
6926         // apply bloom brightness offset
6927         if(r_fb.bloomtexture[0])
6928                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6929
6930         R_Water_StartFrame();
6931
6932         // now we probably have an fbo to render into
6933         fbo = r_fb.fbo;
6934         depthtexture = r_fb.depthtexture;
6935         colortexture = r_fb.colortexture;
6936
6937         CHECKGLERROR
6938         if (r_timereport_active)
6939                 R_TimeReport("viewsetup");
6940
6941         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6942
6943         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6944         {
6945                 R_ClearScreen(r_refdef.fogenabled);
6946                 if (r_timereport_active)
6947                         R_TimeReport("viewclear");
6948         }
6949         r_refdef.view.clear = true;
6950
6951         r_refdef.view.showdebug = true;
6952
6953         R_View_Update();
6954         if (r_timereport_active)
6955                 R_TimeReport("visibility");
6956
6957         R_AnimCache_CacheVisibleEntities();
6958         if (r_timereport_active)
6959                 R_TimeReport("animcache");
6960
6961         R_Shadow_UpdateBounceGridTexture();
6962         if (r_timereport_active && r_shadow_bouncegrid.integer)
6963                 R_TimeReport("bouncegrid");
6964
6965         r_fb.water.numwaterplanes = 0;
6966         if (r_fb.water.enabled)
6967                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6968
6969         R_RenderScene(fbo, depthtexture, colortexture);
6970         r_fb.water.numwaterplanes = 0;
6971
6972         R_BlendView(fbo, depthtexture, colortexture);
6973         if (r_timereport_active)
6974                 R_TimeReport("blendview");
6975
6976         GL_Scissor(0, 0, vid.width, vid.height);
6977         GL_ScissorTest(false);
6978
6979         r_refdef.view.matrix = originalmatrix;
6980
6981         CHECKGLERROR
6982 }
6983
6984 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6985 {
6986         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6987         {
6988                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6989                 if (r_timereport_active)
6990                         R_TimeReport("waterworld");
6991         }
6992
6993         // don't let sound skip if going slow
6994         if (r_refdef.scene.extraupdate)
6995                 S_ExtraUpdate ();
6996
6997         R_DrawModelsAddWaterPlanes();
6998         if (r_timereport_active)
6999                 R_TimeReport("watermodels");
7000
7001         if (r_fb.water.numwaterplanes)
7002         {
7003                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7004                 if (r_timereport_active)
7005                         R_TimeReport("waterscenes");
7006         }
7007 }
7008
7009 extern cvar_t cl_locs_show;
7010 static void R_DrawLocs(void);
7011 static void R_DrawEntityBBoxes(void);
7012 static void R_DrawModelDecals(void);
7013 extern cvar_t cl_decals_newsystem;
7014 extern qboolean r_shadow_usingdeferredprepass;
7015 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7016 {
7017         qboolean shadowmapping = false;
7018
7019         if (r_timereport_active)
7020                 R_TimeReport("beginscene");
7021
7022         r_refdef.stats.renders++;
7023
7024         R_UpdateFog();
7025
7026         // don't let sound skip if going slow
7027         if (r_refdef.scene.extraupdate)
7028                 S_ExtraUpdate ();
7029
7030         R_MeshQueue_BeginScene();
7031
7032         R_SkyStartFrame();
7033
7034         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);
7035
7036         if (r_timereport_active)
7037                 R_TimeReport("skystartframe");
7038
7039         if (cl.csqc_vidvars.drawworld)
7040         {
7041                 // don't let sound skip if going slow
7042                 if (r_refdef.scene.extraupdate)
7043                         S_ExtraUpdate ();
7044
7045                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7046                 {
7047                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7048                         if (r_timereport_active)
7049                                 R_TimeReport("worldsky");
7050                 }
7051
7052                 if (R_DrawBrushModelsSky() && r_timereport_active)
7053                         R_TimeReport("bmodelsky");
7054
7055                 if (skyrendermasked && skyrenderlater)
7056                 {
7057                         // we have to force off the water clipping plane while rendering sky
7058                         R_SetupView(false, fbo, depthtexture, colortexture);
7059                         R_Sky();
7060                         R_SetupView(true, fbo, depthtexture, colortexture);
7061                         if (r_timereport_active)
7062                                 R_TimeReport("sky");
7063                 }
7064         }
7065
7066         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7067         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7068                 R_Shadow_PrepareModelShadows();
7069         if (r_timereport_active)
7070                 R_TimeReport("preparelights");
7071
7072         if (R_Shadow_ShadowMappingEnabled())
7073                 shadowmapping = true;
7074
7075         if (r_shadow_usingdeferredprepass)
7076                 R_Shadow_DrawPrepass();
7077
7078         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7079         {
7080                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7081                 if (r_timereport_active)
7082                         R_TimeReport("worlddepth");
7083         }
7084         if (r_depthfirst.integer >= 2)
7085         {
7086                 R_DrawModelsDepth();
7087                 if (r_timereport_active)
7088                         R_TimeReport("modeldepth");
7089         }
7090
7091         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7092         {
7093                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7094                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7095                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7096                 // don't let sound skip if going slow
7097                 if (r_refdef.scene.extraupdate)
7098                         S_ExtraUpdate ();
7099         }
7100
7101         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7102         {
7103                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7104                 if (r_timereport_active)
7105                         R_TimeReport("world");
7106         }
7107
7108         // don't let sound skip if going slow
7109         if (r_refdef.scene.extraupdate)
7110                 S_ExtraUpdate ();
7111
7112         R_DrawModels();
7113         if (r_timereport_active)
7114                 R_TimeReport("models");
7115
7116         // don't let sound skip if going slow
7117         if (r_refdef.scene.extraupdate)
7118                 S_ExtraUpdate ();
7119
7120         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7121         {
7122                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7123                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7124                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7125                 // don't let sound skip if going slow
7126                 if (r_refdef.scene.extraupdate)
7127                         S_ExtraUpdate ();
7128         }
7129
7130         if (!r_shadow_usingdeferredprepass)
7131         {
7132                 R_Shadow_DrawLights();
7133                 if (r_timereport_active)
7134                         R_TimeReport("rtlights");
7135         }
7136
7137         // don't let sound skip if going slow
7138         if (r_refdef.scene.extraupdate)
7139                 S_ExtraUpdate ();
7140
7141         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7142         {
7143                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7144                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7145                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7146                 // don't let sound skip if going slow
7147                 if (r_refdef.scene.extraupdate)
7148                         S_ExtraUpdate ();
7149         }
7150
7151         if (cl.csqc_vidvars.drawworld)
7152         {
7153                 if (cl_decals_newsystem.integer)
7154                 {
7155                         R_DrawModelDecals();
7156                         if (r_timereport_active)
7157                                 R_TimeReport("modeldecals");
7158                 }
7159                 else
7160                 {
7161                         R_DrawDecals();
7162                         if (r_timereport_active)
7163                                 R_TimeReport("decals");
7164                 }
7165
7166                 R_DrawParticles();
7167                 if (r_timereport_active)
7168                         R_TimeReport("particles");
7169
7170                 R_DrawExplosions();
7171                 if (r_timereport_active)
7172                         R_TimeReport("explosions");
7173
7174                 R_DrawLightningBeams();
7175                 if (r_timereport_active)
7176                         R_TimeReport("lightning");
7177         }
7178
7179         if (cl.csqc_loaded)
7180                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7181
7182         if (r_refdef.view.showdebug)
7183         {
7184                 if (cl_locs_show.integer)
7185                 {
7186                         R_DrawLocs();
7187                         if (r_timereport_active)
7188                                 R_TimeReport("showlocs");
7189                 }
7190
7191                 if (r_drawportals.integer)
7192                 {
7193                         R_DrawPortals();
7194                         if (r_timereport_active)
7195                                 R_TimeReport("portals");
7196                 }
7197
7198                 if (r_showbboxes.value > 0)
7199                 {
7200                         R_DrawEntityBBoxes();
7201                         if (r_timereport_active)
7202                                 R_TimeReport("bboxes");
7203                 }
7204         }
7205
7206         if (r_transparent.integer)
7207         {
7208                 R_MeshQueue_RenderTransparent();
7209                 if (r_timereport_active)
7210                         R_TimeReport("drawtrans");
7211         }
7212
7213         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))
7214         {
7215                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7216                 if (r_timereport_active)
7217                         R_TimeReport("worlddebug");
7218                 R_DrawModelsDebug();
7219                 if (r_timereport_active)
7220                         R_TimeReport("modeldebug");
7221         }
7222
7223         if (cl.csqc_vidvars.drawworld)
7224         {
7225                 R_Shadow_DrawCoronas();
7226                 if (r_timereport_active)
7227                         R_TimeReport("coronas");
7228         }
7229
7230 #if 0
7231         {
7232                 GL_DepthTest(false);
7233                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7234                 GL_Color(1, 1, 1, 1);
7235                 qglBegin(GL_POLYGON);
7236                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7237                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7238                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7239                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7240                 qglEnd();
7241                 qglBegin(GL_POLYGON);
7242                 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]);
7243                 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]);
7244                 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]);
7245                 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]);
7246                 qglEnd();
7247                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7248         }
7249 #endif
7250
7251         // don't let sound skip if going slow
7252         if (r_refdef.scene.extraupdate)
7253                 S_ExtraUpdate ();
7254 }
7255
7256 static const unsigned short bboxelements[36] =
7257 {
7258         5, 1, 3, 5, 3, 7,
7259         6, 2, 0, 6, 0, 4,
7260         7, 3, 2, 7, 2, 6,
7261         4, 0, 1, 4, 1, 5,
7262         4, 5, 7, 4, 7, 6,
7263         1, 0, 2, 1, 2, 3,
7264 };
7265
7266 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7267 {
7268         int i;
7269         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7270
7271         RSurf_ActiveWorldEntity();
7272
7273         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7274         GL_DepthMask(false);
7275         GL_DepthRange(0, 1);
7276         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7277 //      R_Mesh_ResetTextureState();
7278
7279         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7280         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7281         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7282         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7283         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7284         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7285         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7286         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7287         R_FillColors(color4f, 8, cr, cg, cb, ca);
7288         if (r_refdef.fogenabled)
7289         {
7290                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7291                 {
7292                         f1 = RSurf_FogVertex(v);
7293                         f2 = 1 - f1;
7294                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7295                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7296                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7297                 }
7298         }
7299         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7300         R_Mesh_ResetTextureState();
7301         R_SetupShader_Generic_NoTexture(false, false);
7302         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7303 }
7304
7305 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7306 {
7307         prvm_prog_t *prog = SVVM_prog;
7308         int i;
7309         float color[4];
7310         prvm_edict_t *edict;
7311
7312         // this function draws bounding boxes of server entities
7313         if (!sv.active)
7314                 return;
7315
7316         GL_CullFace(GL_NONE);
7317         R_SetupShader_Generic_NoTexture(false, false);
7318
7319         for (i = 0;i < numsurfaces;i++)
7320         {
7321                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7322                 switch ((int)PRVM_serveredictfloat(edict, solid))
7323                 {
7324                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7325                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7326                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7327                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7328                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7329                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7330                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7331                 }
7332                 color[3] *= r_showbboxes.value;
7333                 color[3] = bound(0, color[3], 1);
7334                 GL_DepthTest(!r_showdisabledepthtest.integer);
7335                 GL_CullFace(r_refdef.view.cullface_front);
7336                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7337         }
7338 }
7339
7340 static void R_DrawEntityBBoxes(void)
7341 {
7342         int i;
7343         prvm_edict_t *edict;
7344         vec3_t center;
7345         prvm_prog_t *prog = SVVM_prog;
7346
7347         // this function draws bounding boxes of server entities
7348         if (!sv.active)
7349                 return;
7350
7351         for (i = 0;i < prog->num_edicts;i++)
7352         {
7353                 edict = PRVM_EDICT_NUM(i);
7354                 if (edict->priv.server->free)
7355                         continue;
7356                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7357                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7358                         continue;
7359                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7360                         continue;
7361                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7362                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7363         }
7364 }
7365
7366 static const int nomodelelement3i[24] =
7367 {
7368         5, 2, 0,
7369         5, 1, 2,
7370         5, 0, 3,
7371         5, 3, 1,
7372         0, 2, 4,
7373         2, 1, 4,
7374         3, 0, 4,
7375         1, 3, 4
7376 };
7377
7378 static const unsigned short nomodelelement3s[24] =
7379 {
7380         5, 2, 0,
7381         5, 1, 2,
7382         5, 0, 3,
7383         5, 3, 1,
7384         0, 2, 4,
7385         2, 1, 4,
7386         3, 0, 4,
7387         1, 3, 4
7388 };
7389
7390 static const float nomodelvertex3f[6*3] =
7391 {
7392         -16,   0,   0,
7393          16,   0,   0,
7394           0, -16,   0,
7395           0,  16,   0,
7396           0,   0, -16,
7397           0,   0,  16
7398 };
7399
7400 static const float nomodelcolor4f[6*4] =
7401 {
7402         0.0f, 0.0f, 0.5f, 1.0f,
7403         0.0f, 0.0f, 0.5f, 1.0f,
7404         0.0f, 0.5f, 0.0f, 1.0f,
7405         0.0f, 0.5f, 0.0f, 1.0f,
7406         0.5f, 0.0f, 0.0f, 1.0f,
7407         0.5f, 0.0f, 0.0f, 1.0f
7408 };
7409
7410 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7411 {
7412         int i;
7413         float f1, f2, *c;
7414         float color4f[6*4];
7415
7416         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);
7417
7418         // this is only called once per entity so numsurfaces is always 1, and
7419         // surfacelist is always {0}, so this code does not handle batches
7420
7421         if (rsurface.ent_flags & RENDER_ADDITIVE)
7422         {
7423                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7424                 GL_DepthMask(false);
7425         }
7426         else if (rsurface.colormod[3] < 1)
7427         {
7428                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7429                 GL_DepthMask(false);
7430         }
7431         else
7432         {
7433                 GL_BlendFunc(GL_ONE, GL_ZERO);
7434                 GL_DepthMask(true);
7435         }
7436         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7437         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7438         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7439         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7440         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7441         for (i = 0, c = color4f;i < 6;i++, c += 4)
7442         {
7443                 c[0] *= rsurface.colormod[0];
7444                 c[1] *= rsurface.colormod[1];
7445                 c[2] *= rsurface.colormod[2];
7446                 c[3] *= rsurface.colormod[3];
7447         }
7448         if (r_refdef.fogenabled)
7449         {
7450                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7451                 {
7452                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7453                         f2 = 1 - f1;
7454                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7455                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7456                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7457                 }
7458         }
7459 //      R_Mesh_ResetTextureState();
7460         R_SetupShader_Generic_NoTexture(false, false);
7461         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7462         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7463 }
7464
7465 void R_DrawNoModel(entity_render_t *ent)
7466 {
7467         vec3_t org;
7468         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7469         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7470                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7471         else
7472                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7473 }
7474
7475 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7476 {
7477         vec3_t right1, right2, diff, normal;
7478
7479         VectorSubtract (org2, org1, normal);
7480
7481         // calculate 'right' vector for start
7482         VectorSubtract (r_refdef.view.origin, org1, diff);
7483         CrossProduct (normal, diff, right1);
7484         VectorNormalize (right1);
7485
7486         // calculate 'right' vector for end
7487         VectorSubtract (r_refdef.view.origin, org2, diff);
7488         CrossProduct (normal, diff, right2);
7489         VectorNormalize (right2);
7490
7491         vert[ 0] = org1[0] + width * right1[0];
7492         vert[ 1] = org1[1] + width * right1[1];
7493         vert[ 2] = org1[2] + width * right1[2];
7494         vert[ 3] = org1[0] - width * right1[0];
7495         vert[ 4] = org1[1] - width * right1[1];
7496         vert[ 5] = org1[2] - width * right1[2];
7497         vert[ 6] = org2[0] - width * right2[0];
7498         vert[ 7] = org2[1] - width * right2[1];
7499         vert[ 8] = org2[2] - width * right2[2];
7500         vert[ 9] = org2[0] + width * right2[0];
7501         vert[10] = org2[1] + width * right2[1];
7502         vert[11] = org2[2] + width * right2[2];
7503 }
7504
7505 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)
7506 {
7507         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7508         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7509         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7510         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7511         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7512         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7513         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7514         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7515         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7516         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7517         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7518         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7519 }
7520
7521 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7522 {
7523         int i;
7524         float *vertex3f;
7525         float v[3];
7526         VectorSet(v, x, y, z);
7527         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7528                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7529                         break;
7530         if (i == mesh->numvertices)
7531         {
7532                 if (mesh->numvertices < mesh->maxvertices)
7533                 {
7534                         VectorCopy(v, vertex3f);
7535                         mesh->numvertices++;
7536                 }
7537                 return mesh->numvertices;
7538         }
7539         else
7540                 return i;
7541 }
7542
7543 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7544 {
7545         int i;
7546         int *e, element[3];
7547         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7548         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7549         e = mesh->element3i + mesh->numtriangles * 3;
7550         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7551         {
7552                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7553                 if (mesh->numtriangles < mesh->maxtriangles)
7554                 {
7555                         *e++ = element[0];
7556                         *e++ = element[1];
7557                         *e++ = element[2];
7558                         mesh->numtriangles++;
7559                 }
7560                 element[1] = element[2];
7561         }
7562 }
7563
7564 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7565 {
7566         int i;
7567         int *e, element[3];
7568         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7569         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7570         e = mesh->element3i + mesh->numtriangles * 3;
7571         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7572         {
7573                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7574                 if (mesh->numtriangles < mesh->maxtriangles)
7575                 {
7576                         *e++ = element[0];
7577                         *e++ = element[1];
7578                         *e++ = element[2];
7579                         mesh->numtriangles++;
7580                 }
7581                 element[1] = element[2];
7582         }
7583 }
7584
7585 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7586 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7587 {
7588         int planenum, planenum2;
7589         int w;
7590         int tempnumpoints;
7591         mplane_t *plane, *plane2;
7592         double maxdist;
7593         double temppoints[2][256*3];
7594         // figure out how large a bounding box we need to properly compute this brush
7595         maxdist = 0;
7596         for (w = 0;w < numplanes;w++)
7597                 maxdist = max(maxdist, fabs(planes[w].dist));
7598         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7599         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7600         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7601         {
7602                 w = 0;
7603                 tempnumpoints = 4;
7604                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7605                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7606                 {
7607                         if (planenum2 == planenum)
7608                                 continue;
7609                         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);
7610                         w = !w;
7611                 }
7612                 if (tempnumpoints < 3)
7613                         continue;
7614                 // generate elements forming a triangle fan for this polygon
7615                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7616         }
7617 }
7618
7619 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)
7620 {
7621         texturelayer_t *layer;
7622         layer = t->currentlayers + t->currentnumlayers++;
7623         layer->type = type;
7624         layer->depthmask = depthmask;
7625         layer->blendfunc1 = blendfunc1;
7626         layer->blendfunc2 = blendfunc2;
7627         layer->texture = texture;
7628         layer->texmatrix = *matrix;
7629         layer->color[0] = r;
7630         layer->color[1] = g;
7631         layer->color[2] = b;
7632         layer->color[3] = a;
7633 }
7634
7635 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7636 {
7637         if(parms[0] == 0 && parms[1] == 0)
7638                 return false;
7639         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7640                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7641                         return false;
7642         return true;
7643 }
7644
7645 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7646 {
7647         double index, f;
7648         index = parms[2] + rsurface.shadertime * parms[3];
7649         index -= floor(index);
7650         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7651         {
7652         default:
7653         case Q3WAVEFUNC_NONE:
7654         case Q3WAVEFUNC_NOISE:
7655         case Q3WAVEFUNC_COUNT:
7656                 f = 0;
7657                 break;
7658         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7659         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7660         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7661         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7662         case Q3WAVEFUNC_TRIANGLE:
7663                 index *= 4;
7664                 f = index - floor(index);
7665                 if (index < 1)
7666                 {
7667                         // f = f;
7668                 }
7669                 else if (index < 2)
7670                         f = 1 - f;
7671                 else if (index < 3)
7672                         f = -f;
7673                 else
7674                         f = -(1 - f);
7675                 break;
7676         }
7677         f = parms[0] + parms[1] * f;
7678         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7679                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7680         return (float) f;
7681 }
7682
7683 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7684 {
7685         int w, h, idx;
7686         double f;
7687         double offsetd[2];
7688         float tcmat[12];
7689         matrix4x4_t matrix, temp;
7690         switch(tcmod->tcmod)
7691         {
7692                 case Q3TCMOD_COUNT:
7693                 case Q3TCMOD_NONE:
7694                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7695                                 matrix = r_waterscrollmatrix;
7696                         else
7697                                 matrix = identitymatrix;
7698                         break;
7699                 case Q3TCMOD_ENTITYTRANSLATE:
7700                         // this is used in Q3 to allow the gamecode to control texcoord
7701                         // scrolling on the entity, which is not supported in darkplaces yet.
7702                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7703                         break;
7704                 case Q3TCMOD_ROTATE:
7705                         f = tcmod->parms[0] * rsurface.shadertime;
7706                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7707                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7708                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7709                         break;
7710                 case Q3TCMOD_SCALE:
7711                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7712                         break;
7713                 case Q3TCMOD_SCROLL:
7714                         // extra care is needed because of precision breakdown with large values of time
7715                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7716                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7717                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7718                         break;
7719                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7720                         w = (int) tcmod->parms[0];
7721                         h = (int) tcmod->parms[1];
7722                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7723                         f = f - floor(f);
7724                         idx = (int) floor(f * w * h);
7725                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7726                         break;
7727                 case Q3TCMOD_STRETCH:
7728                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7729                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7730                         break;
7731                 case Q3TCMOD_TRANSFORM:
7732                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7733                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7734                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7735                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7736                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7737                         break;
7738                 case Q3TCMOD_TURBULENT:
7739                         // this is handled in the RSurf_PrepareVertices function
7740                         matrix = identitymatrix;
7741                         break;
7742         }
7743         temp = *texmatrix;
7744         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7745 }
7746
7747 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7748 {
7749         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7750         char name[MAX_QPATH];
7751         skinframe_t *skinframe;
7752         unsigned char pixels[296*194];
7753         strlcpy(cache->name, skinname, sizeof(cache->name));
7754         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7755         if (developer_loading.integer)
7756                 Con_Printf("loading %s\n", name);
7757         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7758         if (!skinframe || !skinframe->base)
7759         {
7760                 unsigned char *f;
7761                 fs_offset_t filesize;
7762                 skinframe = NULL;
7763                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7764                 if (f)
7765                 {
7766                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7767                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7768                         Mem_Free(f);
7769                 }
7770         }
7771         cache->skinframe = skinframe;
7772 }
7773
7774 texture_t *R_GetCurrentTexture(texture_t *t)
7775 {
7776         int i;
7777         const entity_render_t *ent = rsurface.entity;
7778         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7779         q3shaderinfo_layer_tcmod_t *tcmod;
7780
7781         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7782                 return t->currentframe;
7783         t->update_lastrenderframe = r_textureframe;
7784         t->update_lastrenderentity = (void *)ent;
7785
7786         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7787                 t->camera_entity = ent->entitynumber;
7788         else
7789                 t->camera_entity = 0;
7790
7791         // switch to an alternate material if this is a q1bsp animated material
7792         {
7793                 texture_t *texture = t;
7794                 int s = rsurface.ent_skinnum;
7795                 if ((unsigned int)s >= (unsigned int)model->numskins)
7796                         s = 0;
7797                 if (model->skinscenes)
7798                 {
7799                         if (model->skinscenes[s].framecount > 1)
7800                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7801                         else
7802                                 s = model->skinscenes[s].firstframe;
7803                 }
7804                 if (s > 0)
7805                         t = t + s * model->num_surfaces;
7806                 if (t->animated)
7807                 {
7808                         // use an alternate animation if the entity's frame is not 0,
7809                         // and only if the texture has an alternate animation
7810                         if (rsurface.ent_alttextures && t->anim_total[1])
7811                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7812                         else
7813                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7814                 }
7815                 texture->currentframe = t;
7816         }
7817
7818         // update currentskinframe to be a qw skin or animation frame
7819         if (rsurface.ent_qwskin >= 0)
7820         {
7821                 i = rsurface.ent_qwskin;
7822                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7823                 {
7824                         r_qwskincache_size = cl.maxclients;
7825                         if (r_qwskincache)
7826                                 Mem_Free(r_qwskincache);
7827                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7828                 }
7829                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7830                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7831                 t->currentskinframe = r_qwskincache[i].skinframe;
7832                 if (t->currentskinframe == NULL)
7833                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7834         }
7835         else if (t->numskinframes >= 2)
7836                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7837         if (t->backgroundnumskinframes >= 2)
7838                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7839
7840         t->currentmaterialflags = t->basematerialflags;
7841         t->currentalpha = rsurface.colormod[3];
7842         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7843                 t->currentalpha *= r_wateralpha.value;
7844         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7845                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7846         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7847                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7848         if (!(rsurface.ent_flags & RENDER_LIGHT))
7849                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7850         else if (FAKELIGHT_ENABLED)
7851         {
7852                 // no modellight if using fakelight for the map
7853         }
7854         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7855         {
7856                 // pick a model lighting mode
7857                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7858                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7859                 else
7860                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7861         }
7862         if (rsurface.ent_flags & RENDER_ADDITIVE)
7863                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7864         else if (t->currentalpha < 1)
7865                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7866         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7867         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7868                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7869         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7870                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7871         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7872                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7873         if (t->backgroundnumskinframes)
7874                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7875         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7876         {
7877                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7878                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7879         }
7880         else
7881                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7882         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7883         {
7884                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7885                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7886         }
7887         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7888                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7889
7890         // there is no tcmod
7891         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7892         {
7893                 t->currenttexmatrix = r_waterscrollmatrix;
7894                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7895         }
7896         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7897         {
7898                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7899                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7900         }
7901
7902         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7903                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7904         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7905                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7906
7907         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7908         if (t->currentskinframe->qpixels)
7909                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7910         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7911         if (!t->basetexture)
7912                 t->basetexture = r_texture_notexture;
7913         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7914         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7915         t->nmaptexture = t->currentskinframe->nmap;
7916         if (!t->nmaptexture)
7917                 t->nmaptexture = r_texture_blanknormalmap;
7918         t->glosstexture = r_texture_black;
7919         t->glowtexture = t->currentskinframe->glow;
7920         t->fogtexture = t->currentskinframe->fog;
7921         t->reflectmasktexture = t->currentskinframe->reflect;
7922         if (t->backgroundnumskinframes)
7923         {
7924                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7925                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7926                 t->backgroundglosstexture = r_texture_black;
7927                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7928                 if (!t->backgroundnmaptexture)
7929                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7930                 // make sure that if glow is going to be used, both textures are not NULL
7931                 if (!t->backgroundglowtexture && t->glowtexture)
7932                         t->backgroundglowtexture = r_texture_black;
7933                 if (!t->glowtexture && t->backgroundglowtexture)
7934                         t->glowtexture = r_texture_black;
7935         }
7936         else
7937         {
7938                 t->backgroundbasetexture = r_texture_white;
7939                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7940                 t->backgroundglosstexture = r_texture_black;
7941                 t->backgroundglowtexture = NULL;
7942         }
7943         t->specularpower = r_shadow_glossexponent.value;
7944         // TODO: store reference values for these in the texture?
7945         t->specularscale = 0;
7946         if (r_shadow_gloss.integer > 0)
7947         {
7948                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7949                 {
7950                         if (r_shadow_glossintensity.value > 0)
7951                         {
7952                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7953                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7954                                 t->specularscale = r_shadow_glossintensity.value;
7955                         }
7956                 }
7957                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7958                 {
7959                         t->glosstexture = r_texture_white;
7960                         t->backgroundglosstexture = r_texture_white;
7961                         t->specularscale = r_shadow_gloss2intensity.value;
7962                         t->specularpower = r_shadow_gloss2exponent.value;
7963                 }
7964         }
7965         t->specularscale *= t->specularscalemod;
7966         t->specularpower *= t->specularpowermod;
7967         t->rtlightambient = 0;
7968
7969         // lightmaps mode looks bad with dlights using actual texturing, so turn
7970         // off the colormap and glossmap, but leave the normalmap on as it still
7971         // accurately represents the shading involved
7972         if (gl_lightmaps.integer)
7973         {
7974                 t->basetexture = r_texture_grey128;
7975                 t->pantstexture = r_texture_black;
7976                 t->shirttexture = r_texture_black;
7977                 t->nmaptexture = r_texture_blanknormalmap;
7978                 t->glosstexture = r_texture_black;
7979                 t->glowtexture = NULL;
7980                 t->fogtexture = NULL;
7981                 t->reflectmasktexture = NULL;
7982                 t->backgroundbasetexture = NULL;
7983                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7984                 t->backgroundglosstexture = r_texture_black;
7985                 t->backgroundglowtexture = NULL;
7986                 t->specularscale = 0;
7987                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7988         }
7989
7990         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7991         VectorClear(t->dlightcolor);
7992         t->currentnumlayers = 0;
7993         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7994         {
7995                 int blendfunc1, blendfunc2;
7996                 qboolean depthmask;
7997                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7998                 {
7999                         blendfunc1 = GL_SRC_ALPHA;
8000                         blendfunc2 = GL_ONE;
8001                 }
8002                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8003                 {
8004                         blendfunc1 = GL_SRC_ALPHA;
8005                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8006                 }
8007                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8008                 {
8009                         blendfunc1 = t->customblendfunc[0];
8010                         blendfunc2 = t->customblendfunc[1];
8011                 }
8012                 else
8013                 {
8014                         blendfunc1 = GL_ONE;
8015                         blendfunc2 = GL_ZERO;
8016                 }
8017                 // don't colormod evilblend textures
8018                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8019                         VectorSet(t->lightmapcolor, 1, 1, 1);
8020                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8021                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8022                 {
8023                         // fullbright is not affected by r_refdef.lightmapintensity
8024                         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]);
8025                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8026                                 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]);
8027                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8028                                 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]);
8029                 }
8030                 else
8031                 {
8032                         vec3_t ambientcolor;
8033                         float colorscale;
8034                         // set the color tint used for lights affecting this surface
8035                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8036                         colorscale = 2;
8037                         // q3bsp has no lightmap updates, so the lightstylevalue that
8038                         // would normally be baked into the lightmap must be
8039                         // applied to the color
8040                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8041                         if (model->type == mod_brushq3)
8042                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8043                         colorscale *= r_refdef.lightmapintensity;
8044                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8045                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8046                         // basic lit geometry
8047                         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]);
8048                         // add pants/shirt if needed
8049                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8050                                 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]);
8051                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8052                                 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]);
8053                         // now add ambient passes if needed
8054                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8055                         {
8056                                 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]);
8057                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8058                                         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]);
8059                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8060                                         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]);
8061                         }
8062                 }
8063                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8064                         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]);
8065                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8066                 {
8067                         // if this is opaque use alpha blend which will darken the earlier
8068                         // passes cheaply.
8069                         //
8070                         // if this is an alpha blended material, all the earlier passes
8071                         // were darkened by fog already, so we only need to add the fog
8072                         // color ontop through the fog mask texture
8073                         //
8074                         // if this is an additive blended material, all the earlier passes
8075                         // were darkened by fog already, and we should not add fog color
8076                         // (because the background was not darkened, there is no fog color
8077                         // that was lost behind it).
8078                         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]);
8079                 }
8080         }
8081
8082         return t->currentframe;
8083 }
8084
8085 rsurfacestate_t rsurface;
8086
8087 void RSurf_ActiveWorldEntity(void)
8088 {
8089         dp_model_t *model = r_refdef.scene.worldmodel;
8090         //if (rsurface.entity == r_refdef.scene.worldentity)
8091         //      return;
8092         rsurface.entity = r_refdef.scene.worldentity;
8093         rsurface.skeleton = NULL;
8094         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8095         rsurface.ent_skinnum = 0;
8096         rsurface.ent_qwskin = -1;
8097         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8098         rsurface.shadertime = r_refdef.scene.time;
8099         rsurface.matrix = identitymatrix;
8100         rsurface.inversematrix = identitymatrix;
8101         rsurface.matrixscale = 1;
8102         rsurface.inversematrixscale = 1;
8103         R_EntityMatrix(&identitymatrix);
8104         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8105         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8106         rsurface.fograngerecip = r_refdef.fograngerecip;
8107         rsurface.fogheightfade = r_refdef.fogheightfade;
8108         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8109         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8110         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8111         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8112         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8113         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8114         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8115         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8116         rsurface.colormod[3] = 1;
8117         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);
8118         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8119         rsurface.frameblend[0].lerp = 1;
8120         rsurface.ent_alttextures = false;
8121         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8122         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8123         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8124         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8126         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8127         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8129         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8130         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8131         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8132         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8133         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8134         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8135         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8136         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8137         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8138         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8139         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8141         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8142         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8143         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8144         rsurface.modelelement3i = model->surfmesh.data_element3i;
8145         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8146         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8147         rsurface.modelelement3s = model->surfmesh.data_element3s;
8148         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8149         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8150         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8151         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8152         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8153         rsurface.modelsurfaces = model->data_surfaces;
8154         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8155         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8156         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8157         rsurface.modelgeneratedvertex = false;
8158         rsurface.batchgeneratedvertex = false;
8159         rsurface.batchfirstvertex = 0;
8160         rsurface.batchnumvertices = 0;
8161         rsurface.batchfirsttriangle = 0;
8162         rsurface.batchnumtriangles = 0;
8163         rsurface.batchvertex3f  = NULL;
8164         rsurface.batchvertex3f_vertexbuffer = NULL;
8165         rsurface.batchvertex3f_bufferoffset = 0;
8166         rsurface.batchsvector3f = NULL;
8167         rsurface.batchsvector3f_vertexbuffer = NULL;
8168         rsurface.batchsvector3f_bufferoffset = 0;
8169         rsurface.batchtvector3f = NULL;
8170         rsurface.batchtvector3f_vertexbuffer = NULL;
8171         rsurface.batchtvector3f_bufferoffset = 0;
8172         rsurface.batchnormal3f  = NULL;
8173         rsurface.batchnormal3f_vertexbuffer = NULL;
8174         rsurface.batchnormal3f_bufferoffset = 0;
8175         rsurface.batchlightmapcolor4f = NULL;
8176         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8177         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8178         rsurface.batchtexcoordtexture2f = NULL;
8179         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8180         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8181         rsurface.batchtexcoordlightmap2f = NULL;
8182         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8183         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8184         rsurface.batchvertexmesh = NULL;
8185         rsurface.batchvertexmeshbuffer = NULL;
8186         rsurface.batchvertex3fbuffer = NULL;
8187         rsurface.batchelement3i = NULL;
8188         rsurface.batchelement3i_indexbuffer = NULL;
8189         rsurface.batchelement3i_bufferoffset = 0;
8190         rsurface.batchelement3s = NULL;
8191         rsurface.batchelement3s_indexbuffer = NULL;
8192         rsurface.batchelement3s_bufferoffset = 0;
8193         rsurface.passcolor4f = NULL;
8194         rsurface.passcolor4f_vertexbuffer = NULL;
8195         rsurface.passcolor4f_bufferoffset = 0;
8196         rsurface.forcecurrenttextureupdate = false;
8197 }
8198
8199 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8200 {
8201         dp_model_t *model = ent->model;
8202         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8203         //      return;
8204         rsurface.entity = (entity_render_t *)ent;
8205         rsurface.skeleton = ent->skeleton;
8206         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8207         rsurface.ent_skinnum = ent->skinnum;
8208         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;
8209         rsurface.ent_flags = ent->flags;
8210         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8211         rsurface.matrix = ent->matrix;
8212         rsurface.inversematrix = ent->inversematrix;
8213         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8214         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8215         R_EntityMatrix(&rsurface.matrix);
8216         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8217         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8218         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8219         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8220         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8221         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8222         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8223         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8224         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8225         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8226         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8227         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8228         rsurface.colormod[3] = ent->alpha;
8229         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8230         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8231         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8232         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8233         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8234         if (ent->model->brush.submodel && !prepass)
8235         {
8236                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8237                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8238         }
8239         if (model->surfmesh.isanimated && model->AnimateVertices)
8240         {
8241                 if (ent->animcache_vertex3f)
8242                 {
8243                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8244                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8245                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8246                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8247                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8248                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8249                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8250                 }
8251                 else if (wanttangents)
8252                 {
8253                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8254                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8255                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8256                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8257                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8258                         rsurface.modelvertexmesh = NULL;
8259                         rsurface.modelvertexmeshbuffer = NULL;
8260                         rsurface.modelvertex3fbuffer = NULL;
8261                 }
8262                 else if (wantnormals)
8263                 {
8264                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8265                         rsurface.modelsvector3f = NULL;
8266                         rsurface.modeltvector3f = NULL;
8267                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8268                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8269                         rsurface.modelvertexmesh = NULL;
8270                         rsurface.modelvertexmeshbuffer = NULL;
8271                         rsurface.modelvertex3fbuffer = NULL;
8272                 }
8273                 else
8274                 {
8275                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8276                         rsurface.modelsvector3f = NULL;
8277                         rsurface.modeltvector3f = NULL;
8278                         rsurface.modelnormal3f = NULL;
8279                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8280                         rsurface.modelvertexmesh = NULL;
8281                         rsurface.modelvertexmeshbuffer = NULL;
8282                         rsurface.modelvertex3fbuffer = NULL;
8283                 }
8284                 rsurface.modelvertex3f_vertexbuffer = 0;
8285                 rsurface.modelvertex3f_bufferoffset = 0;
8286                 rsurface.modelsvector3f_vertexbuffer = 0;
8287                 rsurface.modelsvector3f_bufferoffset = 0;
8288                 rsurface.modeltvector3f_vertexbuffer = 0;
8289                 rsurface.modeltvector3f_bufferoffset = 0;
8290                 rsurface.modelnormal3f_vertexbuffer = 0;
8291                 rsurface.modelnormal3f_bufferoffset = 0;
8292                 rsurface.modelgeneratedvertex = true;
8293         }
8294         else
8295         {
8296                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8297                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8298                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8299                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8300                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8301                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8302                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8303                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8304                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8305                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8306                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8307                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8308                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8309                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8310                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8311                 rsurface.modelgeneratedvertex = false;
8312         }
8313         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8314         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8315         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8316         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8317         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8318         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8319         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8320         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8321         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8322         rsurface.modelelement3i = model->surfmesh.data_element3i;
8323         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8324         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8325         rsurface.modelelement3s = model->surfmesh.data_element3s;
8326         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8327         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8328         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8329         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8330         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8331         rsurface.modelsurfaces = model->data_surfaces;
8332         rsurface.batchgeneratedvertex = false;
8333         rsurface.batchfirstvertex = 0;
8334         rsurface.batchnumvertices = 0;
8335         rsurface.batchfirsttriangle = 0;
8336         rsurface.batchnumtriangles = 0;
8337         rsurface.batchvertex3f  = NULL;
8338         rsurface.batchvertex3f_vertexbuffer = NULL;
8339         rsurface.batchvertex3f_bufferoffset = 0;
8340         rsurface.batchsvector3f = NULL;
8341         rsurface.batchsvector3f_vertexbuffer = NULL;
8342         rsurface.batchsvector3f_bufferoffset = 0;
8343         rsurface.batchtvector3f = NULL;
8344         rsurface.batchtvector3f_vertexbuffer = NULL;
8345         rsurface.batchtvector3f_bufferoffset = 0;
8346         rsurface.batchnormal3f  = NULL;
8347         rsurface.batchnormal3f_vertexbuffer = NULL;
8348         rsurface.batchnormal3f_bufferoffset = 0;
8349         rsurface.batchlightmapcolor4f = NULL;
8350         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8351         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8352         rsurface.batchtexcoordtexture2f = NULL;
8353         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8354         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8355         rsurface.batchtexcoordlightmap2f = NULL;
8356         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8357         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8358         rsurface.batchvertexmesh = NULL;
8359         rsurface.batchvertexmeshbuffer = NULL;
8360         rsurface.batchvertex3fbuffer = NULL;
8361         rsurface.batchelement3i = NULL;
8362         rsurface.batchelement3i_indexbuffer = NULL;
8363         rsurface.batchelement3i_bufferoffset = 0;
8364         rsurface.batchelement3s = NULL;
8365         rsurface.batchelement3s_indexbuffer = NULL;
8366         rsurface.batchelement3s_bufferoffset = 0;
8367         rsurface.passcolor4f = NULL;
8368         rsurface.passcolor4f_vertexbuffer = NULL;
8369         rsurface.passcolor4f_bufferoffset = 0;
8370         rsurface.forcecurrenttextureupdate = false;
8371 }
8372
8373 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)
8374 {
8375         rsurface.entity = r_refdef.scene.worldentity;
8376         rsurface.skeleton = NULL;
8377         rsurface.ent_skinnum = 0;
8378         rsurface.ent_qwskin = -1;
8379         rsurface.ent_flags = entflags;
8380         rsurface.shadertime = r_refdef.scene.time - shadertime;
8381         rsurface.modelnumvertices = numvertices;
8382         rsurface.modelnumtriangles = numtriangles;
8383         rsurface.matrix = *matrix;
8384         rsurface.inversematrix = *inversematrix;
8385         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8386         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8387         R_EntityMatrix(&rsurface.matrix);
8388         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8389         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8390         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8391         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8392         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8393         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8394         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8395         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8396         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8397         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8398         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8399         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8400         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);
8401         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8402         rsurface.frameblend[0].lerp = 1;
8403         rsurface.ent_alttextures = false;
8404         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8405         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8406         if (wanttangents)
8407         {
8408                 rsurface.modelvertex3f = (float *)vertex3f;
8409                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8410                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8411                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8412         }
8413         else if (wantnormals)
8414         {
8415                 rsurface.modelvertex3f = (float *)vertex3f;
8416                 rsurface.modelsvector3f = NULL;
8417                 rsurface.modeltvector3f = NULL;
8418                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8419         }
8420         else
8421         {
8422                 rsurface.modelvertex3f = (float *)vertex3f;
8423                 rsurface.modelsvector3f = NULL;
8424                 rsurface.modeltvector3f = NULL;
8425                 rsurface.modelnormal3f = NULL;
8426         }
8427         rsurface.modelvertexmesh = NULL;
8428         rsurface.modelvertexmeshbuffer = NULL;
8429         rsurface.modelvertex3fbuffer = NULL;
8430         rsurface.modelvertex3f_vertexbuffer = 0;
8431         rsurface.modelvertex3f_bufferoffset = 0;
8432         rsurface.modelsvector3f_vertexbuffer = 0;
8433         rsurface.modelsvector3f_bufferoffset = 0;
8434         rsurface.modeltvector3f_vertexbuffer = 0;
8435         rsurface.modeltvector3f_bufferoffset = 0;
8436         rsurface.modelnormal3f_vertexbuffer = 0;
8437         rsurface.modelnormal3f_bufferoffset = 0;
8438         rsurface.modelgeneratedvertex = true;
8439         rsurface.modellightmapcolor4f  = (float *)color4f;
8440         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8441         rsurface.modellightmapcolor4f_bufferoffset = 0;
8442         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8443         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8444         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8445         rsurface.modeltexcoordlightmap2f  = NULL;
8446         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8447         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8448         rsurface.modelelement3i = (int *)element3i;
8449         rsurface.modelelement3i_indexbuffer = NULL;
8450         rsurface.modelelement3i_bufferoffset = 0;
8451         rsurface.modelelement3s = (unsigned short *)element3s;
8452         rsurface.modelelement3s_indexbuffer = NULL;
8453         rsurface.modelelement3s_bufferoffset = 0;
8454         rsurface.modellightmapoffsets = NULL;
8455         rsurface.modelsurfaces = NULL;
8456         rsurface.batchgeneratedvertex = false;
8457         rsurface.batchfirstvertex = 0;
8458         rsurface.batchnumvertices = 0;
8459         rsurface.batchfirsttriangle = 0;
8460         rsurface.batchnumtriangles = 0;
8461         rsurface.batchvertex3f  = NULL;
8462         rsurface.batchvertex3f_vertexbuffer = NULL;
8463         rsurface.batchvertex3f_bufferoffset = 0;
8464         rsurface.batchsvector3f = NULL;
8465         rsurface.batchsvector3f_vertexbuffer = NULL;
8466         rsurface.batchsvector3f_bufferoffset = 0;
8467         rsurface.batchtvector3f = NULL;
8468         rsurface.batchtvector3f_vertexbuffer = NULL;
8469         rsurface.batchtvector3f_bufferoffset = 0;
8470         rsurface.batchnormal3f  = NULL;
8471         rsurface.batchnormal3f_vertexbuffer = NULL;
8472         rsurface.batchnormal3f_bufferoffset = 0;
8473         rsurface.batchlightmapcolor4f = NULL;
8474         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8475         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8476         rsurface.batchtexcoordtexture2f = NULL;
8477         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8478         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8479         rsurface.batchtexcoordlightmap2f = NULL;
8480         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8481         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8482         rsurface.batchvertexmesh = NULL;
8483         rsurface.batchvertexmeshbuffer = NULL;
8484         rsurface.batchvertex3fbuffer = NULL;
8485         rsurface.batchelement3i = NULL;
8486         rsurface.batchelement3i_indexbuffer = NULL;
8487         rsurface.batchelement3i_bufferoffset = 0;
8488         rsurface.batchelement3s = NULL;
8489         rsurface.batchelement3s_indexbuffer = NULL;
8490         rsurface.batchelement3s_bufferoffset = 0;
8491         rsurface.passcolor4f = NULL;
8492         rsurface.passcolor4f_vertexbuffer = NULL;
8493         rsurface.passcolor4f_bufferoffset = 0;
8494         rsurface.forcecurrenttextureupdate = true;
8495
8496         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8497         {
8498                 if ((wantnormals || wanttangents) && !normal3f)
8499                 {
8500                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8501                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8502                 }
8503                 if (wanttangents && !svector3f)
8504                 {
8505                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8506                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8507                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8508                 }
8509         }
8510 }
8511
8512 float RSurf_FogPoint(const float *v)
8513 {
8514         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8515         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8516         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8517         float FogHeightFade = r_refdef.fogheightfade;
8518         float fogfrac;
8519         unsigned int fogmasktableindex;
8520         if (r_refdef.fogplaneviewabove)
8521                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8522         else
8523                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8524         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8525         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8526 }
8527
8528 float RSurf_FogVertex(const float *v)
8529 {
8530         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8531         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8532         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8533         float FogHeightFade = rsurface.fogheightfade;
8534         float fogfrac;
8535         unsigned int fogmasktableindex;
8536         if (r_refdef.fogplaneviewabove)
8537                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8538         else
8539                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8540         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8541         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8542 }
8543
8544 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8545 {
8546         int i;
8547         for (i = 0;i < numelements;i++)
8548                 outelement3i[i] = inelement3i[i] + adjust;
8549 }
8550
8551 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8552 extern cvar_t gl_vbo;
8553 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8554 {
8555         int deformindex;
8556         int firsttriangle;
8557         int numtriangles;
8558         int firstvertex;
8559         int endvertex;
8560         int numvertices;
8561         int surfacefirsttriangle;
8562         int surfacenumtriangles;
8563         int surfacefirstvertex;
8564         int surfaceendvertex;
8565         int surfacenumvertices;
8566         int batchnumvertices;
8567         int batchnumtriangles;
8568         int needsupdate;
8569         int i, j;
8570         qboolean gaps;
8571         qboolean dynamicvertex;
8572         float amplitude;
8573         float animpos;
8574         float scale;
8575         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8576         float waveparms[4];
8577         q3shaderinfo_deform_t *deform;
8578         const msurface_t *surface, *firstsurface;
8579         r_vertexmesh_t *vertexmesh;
8580         if (!texturenumsurfaces)
8581                 return;
8582         // find vertex range of this surface batch
8583         gaps = false;
8584         firstsurface = texturesurfacelist[0];
8585         firsttriangle = firstsurface->num_firsttriangle;
8586         batchnumvertices = 0;
8587         batchnumtriangles = 0;
8588         firstvertex = endvertex = firstsurface->num_firstvertex;
8589         for (i = 0;i < texturenumsurfaces;i++)
8590         {
8591                 surface = texturesurfacelist[i];
8592                 if (surface != firstsurface + i)
8593                         gaps = true;
8594                 surfacefirstvertex = surface->num_firstvertex;
8595                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8596                 surfacenumvertices = surface->num_vertices;
8597                 surfacenumtriangles = surface->num_triangles;
8598                 if (firstvertex > surfacefirstvertex)
8599                         firstvertex = surfacefirstvertex;
8600                 if (endvertex < surfaceendvertex)
8601                         endvertex = surfaceendvertex;
8602                 batchnumvertices += surfacenumvertices;
8603                 batchnumtriangles += surfacenumtriangles;
8604         }
8605
8606         // we now know the vertex range used, and if there are any gaps in it
8607         rsurface.batchfirstvertex = firstvertex;
8608         rsurface.batchnumvertices = endvertex - firstvertex;
8609         rsurface.batchfirsttriangle = firsttriangle;
8610         rsurface.batchnumtriangles = batchnumtriangles;
8611
8612         // this variable holds flags for which properties have been updated that
8613         // may require regenerating vertexmesh array...
8614         needsupdate = 0;
8615
8616         // check if any dynamic vertex processing must occur
8617         dynamicvertex = false;
8618
8619         // if there is a chance of animated vertex colors, it's a dynamic batch
8620         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8621         {
8622                 dynamicvertex = true;
8623                 batchneed |= BATCHNEED_NOGAPS;
8624                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8625         }
8626
8627         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8628         {
8629                 switch (deform->deform)
8630                 {
8631                 default:
8632                 case Q3DEFORM_PROJECTIONSHADOW:
8633                 case Q3DEFORM_TEXT0:
8634                 case Q3DEFORM_TEXT1:
8635                 case Q3DEFORM_TEXT2:
8636                 case Q3DEFORM_TEXT3:
8637                 case Q3DEFORM_TEXT4:
8638                 case Q3DEFORM_TEXT5:
8639                 case Q3DEFORM_TEXT6:
8640                 case Q3DEFORM_TEXT7:
8641                 case Q3DEFORM_NONE:
8642                         break;
8643                 case Q3DEFORM_AUTOSPRITE:
8644                         dynamicvertex = true;
8645                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8646                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8647                         break;
8648                 case Q3DEFORM_AUTOSPRITE2:
8649                         dynamicvertex = true;
8650                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8652                         break;
8653                 case Q3DEFORM_NORMAL:
8654                         dynamicvertex = true;
8655                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8657                         break;
8658                 case Q3DEFORM_WAVE:
8659                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8660                                 break; // if wavefunc is a nop, ignore this transform
8661                         dynamicvertex = true;
8662                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8663                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8664                         break;
8665                 case Q3DEFORM_BULGE:
8666                         dynamicvertex = true;
8667                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8668                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8669                         break;
8670                 case Q3DEFORM_MOVE:
8671                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8672                                 break; // if wavefunc is a nop, ignore this transform
8673                         dynamicvertex = true;
8674                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8675                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8676                         break;
8677                 }
8678         }
8679         switch(rsurface.texture->tcgen.tcgen)
8680         {
8681         default:
8682         case Q3TCGEN_TEXTURE:
8683                 break;
8684         case Q3TCGEN_LIGHTMAP:
8685                 dynamicvertex = true;
8686                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8687                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8688                 break;
8689         case Q3TCGEN_VECTOR:
8690                 dynamicvertex = true;
8691                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8692                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8693                 break;
8694         case Q3TCGEN_ENVIRONMENT:
8695                 dynamicvertex = true;
8696                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8697                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8698                 break;
8699         }
8700         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8701         {
8702                 dynamicvertex = true;
8703                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8704                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8705         }
8706
8707         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8708         {
8709                 dynamicvertex = true;
8710                 batchneed |= BATCHNEED_NOGAPS;
8711                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8712         }
8713
8714         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8715         {
8716                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8717                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8718                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8719                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8720                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8721                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8722                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8723         }
8724
8725         // when the model data has no vertex buffer (dynamic mesh), we need to
8726         // eliminate gaps
8727         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8728                 batchneed |= BATCHNEED_NOGAPS;
8729
8730         // if needsupdate, we have to do a dynamic vertex batch for sure
8731         if (needsupdate & batchneed)
8732                 dynamicvertex = true;
8733
8734         // see if we need to build vertexmesh from arrays
8735         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8736                 dynamicvertex = true;
8737
8738         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8739         // also some drivers strongly dislike firstvertex
8740         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8741                 dynamicvertex = true;
8742
8743         rsurface.batchvertex3f = rsurface.modelvertex3f;
8744         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8745         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8746         rsurface.batchsvector3f = rsurface.modelsvector3f;
8747         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8748         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8749         rsurface.batchtvector3f = rsurface.modeltvector3f;
8750         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8751         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8752         rsurface.batchnormal3f = rsurface.modelnormal3f;
8753         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8754         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8755         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8756         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8757         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8758         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8759         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8760         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8761         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8762         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8763         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8764         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8765         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8766         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8767         rsurface.batchelement3i = rsurface.modelelement3i;
8768         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8769         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8770         rsurface.batchelement3s = rsurface.modelelement3s;
8771         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8772         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8773
8774         // if any dynamic vertex processing has to occur in software, we copy the
8775         // entire surface list together before processing to rebase the vertices
8776         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8777         //
8778         // if any gaps exist and we do not have a static vertex buffer, we have to
8779         // copy the surface list together to avoid wasting upload bandwidth on the
8780         // vertices in the gaps.
8781         //
8782         // if gaps exist and we have a static vertex buffer, we still have to
8783         // combine the index buffer ranges into one dynamic index buffer.
8784         //
8785         // in all cases we end up with data that can be drawn in one call.
8786
8787         if (!dynamicvertex)
8788         {
8789                 // static vertex data, just set pointers...
8790                 rsurface.batchgeneratedvertex = false;
8791                 // if there are gaps, we want to build a combined index buffer,
8792                 // otherwise use the original static buffer with an appropriate offset
8793                 if (gaps)
8794                 {
8795                         // build a new triangle elements array for this batch
8796                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8797                         rsurface.batchfirsttriangle = 0;
8798                         numtriangles = 0;
8799                         for (i = 0;i < texturenumsurfaces;i++)
8800                         {
8801                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8802                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8803                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8804                                 numtriangles += surfacenumtriangles;
8805                         }
8806                         rsurface.batchelement3i_indexbuffer = NULL;
8807                         rsurface.batchelement3i_bufferoffset = 0;
8808                         rsurface.batchelement3s = NULL;
8809                         rsurface.batchelement3s_indexbuffer = NULL;
8810                         rsurface.batchelement3s_bufferoffset = 0;
8811                         if (endvertex <= 65536)
8812                         {
8813                                 // make a 16bit (unsigned short) index array if possible
8814                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8815                                 for (i = 0;i < numtriangles*3;i++)
8816                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8817                         }
8818                 }
8819                 return;
8820         }
8821
8822         // something needs software processing, do it for real...
8823         // we only directly handle separate array data in this case and then
8824         // generate interleaved data if needed...
8825         rsurface.batchgeneratedvertex = true;
8826
8827         // now copy the vertex data into a combined array and make an index array
8828         // (this is what Quake3 does all the time)
8829         //if (gaps || rsurface.batchfirstvertex)
8830         {
8831                 rsurface.batchvertex3fbuffer = NULL;
8832                 rsurface.batchvertexmesh = NULL;
8833                 rsurface.batchvertexmeshbuffer = NULL;
8834                 rsurface.batchvertex3f = NULL;
8835                 rsurface.batchvertex3f_vertexbuffer = NULL;
8836                 rsurface.batchvertex3f_bufferoffset = 0;
8837                 rsurface.batchsvector3f = NULL;
8838                 rsurface.batchsvector3f_vertexbuffer = NULL;
8839                 rsurface.batchsvector3f_bufferoffset = 0;
8840                 rsurface.batchtvector3f = NULL;
8841                 rsurface.batchtvector3f_vertexbuffer = NULL;
8842                 rsurface.batchtvector3f_bufferoffset = 0;
8843                 rsurface.batchnormal3f = NULL;
8844                 rsurface.batchnormal3f_vertexbuffer = NULL;
8845                 rsurface.batchnormal3f_bufferoffset = 0;
8846                 rsurface.batchlightmapcolor4f = NULL;
8847                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8848                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8849                 rsurface.batchtexcoordtexture2f = NULL;
8850                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8851                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8852                 rsurface.batchtexcoordlightmap2f = NULL;
8853                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8854                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8855                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8856                 rsurface.batchelement3i_indexbuffer = NULL;
8857                 rsurface.batchelement3i_bufferoffset = 0;
8858                 rsurface.batchelement3s = NULL;
8859                 rsurface.batchelement3s_indexbuffer = NULL;
8860                 rsurface.batchelement3s_bufferoffset = 0;
8861                 // we'll only be setting up certain arrays as needed
8862                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8863                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8864                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8865                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8866                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8867                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8869                 {
8870                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8872                 }
8873                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8874                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8875                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8876                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8877                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8878                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8879                 numvertices = 0;
8880                 numtriangles = 0;
8881                 for (i = 0;i < texturenumsurfaces;i++)
8882                 {
8883                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8884                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8885                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8886                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8887                         // copy only the data requested
8888                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8889                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8890                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8891                         {
8892                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8893                                 {
8894                                         if (rsurface.batchvertex3f)
8895                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8896                                         else
8897                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8898                                 }
8899                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8900                                 {
8901                                         if (rsurface.modelnormal3f)
8902                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8903                                         else
8904                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8905                                 }
8906                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8907                                 {
8908                                         if (rsurface.modelsvector3f)
8909                                         {
8910                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8911                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8912                                         }
8913                                         else
8914                                         {
8915                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8916                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8917                                         }
8918                                 }
8919                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8920                                 {
8921                                         if (rsurface.modellightmapcolor4f)
8922                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8923                                         else
8924                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8925                                 }
8926                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8927                                 {
8928                                         if (rsurface.modeltexcoordtexture2f)
8929                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8930                                         else
8931                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8932                                 }
8933                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8934                                 {
8935                                         if (rsurface.modeltexcoordlightmap2f)
8936                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8937                                         else
8938                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8939                                 }
8940                         }
8941                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8942                         numvertices += surfacenumvertices;
8943                         numtriangles += surfacenumtriangles;
8944                 }
8945
8946                 // generate a 16bit index array as well if possible
8947                 // (in general, dynamic batches fit)
8948                 if (numvertices <= 65536)
8949                 {
8950                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8951                         for (i = 0;i < numtriangles*3;i++)
8952                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8953                 }
8954
8955                 // since we've copied everything, the batch now starts at 0
8956                 rsurface.batchfirstvertex = 0;
8957                 rsurface.batchnumvertices = batchnumvertices;
8958                 rsurface.batchfirsttriangle = 0;
8959                 rsurface.batchnumtriangles = batchnumtriangles;
8960         }
8961
8962         // q1bsp surfaces rendered in vertex color mode have to have colors
8963         // calculated based on lightstyles
8964         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8965         {
8966                 // generate color arrays for the surfaces in this list
8967                 int c[4];
8968                 int scale;
8969                 int size3;
8970                 const int *offsets;
8971                 const unsigned char *lm;
8972                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8973                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8974                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8975                 numvertices = 0;
8976                 for (i = 0;i < texturenumsurfaces;i++)
8977                 {
8978                         surface = texturesurfacelist[i];
8979                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8980                         surfacenumvertices = surface->num_vertices;
8981                         if (surface->lightmapinfo->samples)
8982                         {
8983                                 for (j = 0;j < surfacenumvertices;j++)
8984                                 {
8985                                         lm = surface->lightmapinfo->samples + offsets[j];
8986                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8987                                         VectorScale(lm, scale, c);
8988                                         if (surface->lightmapinfo->styles[1] != 255)
8989                                         {
8990                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8991                                                 lm += size3;
8992                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8993                                                 VectorMA(c, scale, lm, c);
8994                                                 if (surface->lightmapinfo->styles[2] != 255)
8995                                                 {
8996                                                         lm += size3;
8997                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8998                                                         VectorMA(c, scale, lm, c);
8999                                                         if (surface->lightmapinfo->styles[3] != 255)
9000                                                         {
9001                                                                 lm += size3;
9002                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9003                                                                 VectorMA(c, scale, lm, c);
9004                                                         }
9005                                                 }
9006                                         }
9007                                         c[0] >>= 7;
9008                                         c[1] >>= 7;
9009                                         c[2] >>= 7;
9010                                         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);
9011                                         numvertices++;
9012                                 }
9013                         }
9014                         else
9015                         {
9016                                 for (j = 0;j < surfacenumvertices;j++)
9017                                 {
9018                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9019                                         numvertices++;
9020                                 }
9021                         }
9022                 }
9023         }
9024
9025         // if vertices are deformed (sprite flares and things in maps, possibly
9026         // water waves, bulges and other deformations), modify the copied vertices
9027         // in place
9028         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9029         {
9030                 switch (deform->deform)
9031                 {
9032                 default:
9033                 case Q3DEFORM_PROJECTIONSHADOW:
9034                 case Q3DEFORM_TEXT0:
9035                 case Q3DEFORM_TEXT1:
9036                 case Q3DEFORM_TEXT2:
9037                 case Q3DEFORM_TEXT3:
9038                 case Q3DEFORM_TEXT4:
9039                 case Q3DEFORM_TEXT5:
9040                 case Q3DEFORM_TEXT6:
9041                 case Q3DEFORM_TEXT7:
9042                 case Q3DEFORM_NONE:
9043                         break;
9044                 case Q3DEFORM_AUTOSPRITE:
9045                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9046                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9047                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9048                         VectorNormalize(newforward);
9049                         VectorNormalize(newright);
9050                         VectorNormalize(newup);
9051 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9052 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9053 //                      rsurface.batchvertex3f_bufferoffset = 0;
9054 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9055 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9056 //                      rsurface.batchsvector3f_bufferoffset = 0;
9057 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9058 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9059 //                      rsurface.batchtvector3f_bufferoffset = 0;
9060 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9061 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9062 //                      rsurface.batchnormal3f_bufferoffset = 0;
9063                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9064                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9065                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9066                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9067                                 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);
9068                         // a single autosprite surface can contain multiple sprites...
9069                         for (j = 0;j < batchnumvertices - 3;j += 4)
9070                         {
9071                                 VectorClear(center);
9072                                 for (i = 0;i < 4;i++)
9073                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9074                                 VectorScale(center, 0.25f, center);
9075                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9076                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9077                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9078                                 for (i = 0;i < 4;i++)
9079                                 {
9080                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9081                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9082                                 }
9083                         }
9084                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9085                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9086                         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);
9087                         break;
9088                 case Q3DEFORM_AUTOSPRITE2:
9089                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9090                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9091                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9092                         VectorNormalize(newforward);
9093                         VectorNormalize(newright);
9094                         VectorNormalize(newup);
9095 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9096 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9097 //                      rsurface.batchvertex3f_bufferoffset = 0;
9098                         {
9099                                 const float *v1, *v2;
9100                                 vec3_t start, end;
9101                                 float f, l;
9102                                 struct
9103                                 {
9104                                         float length2;
9105                                         const float *v1;
9106                                         const float *v2;
9107                                 }
9108                                 shortest[2];
9109                                 memset(shortest, 0, sizeof(shortest));
9110                                 // a single autosprite surface can contain multiple sprites...
9111                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9112                                 {
9113                                         VectorClear(center);
9114                                         for (i = 0;i < 4;i++)
9115                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9116                                         VectorScale(center, 0.25f, center);
9117                                         // find the two shortest edges, then use them to define the
9118                                         // axis vectors for rotating around the central axis
9119                                         for (i = 0;i < 6;i++)
9120                                         {
9121                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9122                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9123                                                 l = VectorDistance2(v1, v2);
9124                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9125                                                 if (v1[2] != v2[2])
9126                                                         l += (1.0f / 1024.0f);
9127                                                 if (shortest[0].length2 > l || i == 0)
9128                                                 {
9129                                                         shortest[1] = shortest[0];
9130                                                         shortest[0].length2 = l;
9131                                                         shortest[0].v1 = v1;
9132                                                         shortest[0].v2 = v2;
9133                                                 }
9134                                                 else if (shortest[1].length2 > l || i == 1)
9135                                                 {
9136                                                         shortest[1].length2 = l;
9137                                                         shortest[1].v1 = v1;
9138                                                         shortest[1].v2 = v2;
9139                                                 }
9140                                         }
9141                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9142                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9143                                         // this calculates the right vector from the shortest edge
9144                                         // and the up vector from the edge midpoints
9145                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9146                                         VectorNormalize(right);
9147                                         VectorSubtract(end, start, up);
9148                                         VectorNormalize(up);
9149                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9150                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9151                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9152                                         VectorNegate(forward, forward);
9153                                         VectorReflect(forward, 0, up, forward);
9154                                         VectorNormalize(forward);
9155                                         CrossProduct(up, forward, newright);
9156                                         VectorNormalize(newright);
9157                                         // rotate the quad around the up axis vector, this is made
9158                                         // especially easy by the fact we know the quad is flat,
9159                                         // so we only have to subtract the center position and
9160                                         // measure distance along the right vector, and then
9161                                         // multiply that by the newright vector and add back the
9162                                         // center position
9163                                         // we also need to subtract the old position to undo the
9164                                         // displacement from the center, which we do with a
9165                                         // DotProduct, the subtraction/addition of center is also
9166                                         // optimized into DotProducts here
9167                                         l = DotProduct(right, center);
9168                                         for (i = 0;i < 4;i++)
9169                                         {
9170                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9171                                                 f = DotProduct(right, v1) - l;
9172                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9173                                         }
9174                                 }
9175                         }
9176                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9177                         {
9178 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9179 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9180 //                              rsurface.batchnormal3f_bufferoffset = 0;
9181                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9182                         }
9183                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9184                         {
9185 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9186 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9187 //                              rsurface.batchsvector3f_bufferoffset = 0;
9188 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9189 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9190 //                              rsurface.batchtvector3f_bufferoffset = 0;
9191                                 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);
9192                         }
9193                         break;
9194                 case Q3DEFORM_NORMAL:
9195                         // deform the normals to make reflections wavey
9196                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9197                         rsurface.batchnormal3f_vertexbuffer = NULL;
9198                         rsurface.batchnormal3f_bufferoffset = 0;
9199                         for (j = 0;j < batchnumvertices;j++)
9200                         {
9201                                 float vertex[3];
9202                                 float *normal = rsurface.batchnormal3f + 3*j;
9203                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9204                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9205                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9206                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9207                                 VectorNormalize(normal);
9208                         }
9209                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9210                         {
9211 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9212 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9213 //                              rsurface.batchsvector3f_bufferoffset = 0;
9214 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9215 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9216 //                              rsurface.batchtvector3f_bufferoffset = 0;
9217                                 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);
9218                         }
9219                         break;
9220                 case Q3DEFORM_WAVE:
9221                         // deform vertex array to make wavey water and flags and such
9222                         waveparms[0] = deform->waveparms[0];
9223                         waveparms[1] = deform->waveparms[1];
9224                         waveparms[2] = deform->waveparms[2];
9225                         waveparms[3] = deform->waveparms[3];
9226                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9227                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9228                         // this is how a divisor of vertex influence on deformation
9229                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9230                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9231 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9232 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9233 //                      rsurface.batchvertex3f_bufferoffset = 0;
9234 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9235 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9236 //                      rsurface.batchnormal3f_bufferoffset = 0;
9237                         for (j = 0;j < batchnumvertices;j++)
9238                         {
9239                                 // if the wavefunc depends on time, evaluate it per-vertex
9240                                 if (waveparms[3])
9241                                 {
9242                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9243                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9244                                 }
9245                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9246                         }
9247                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9248                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9249                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9250                         {
9251 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9252 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9253 //                              rsurface.batchsvector3f_bufferoffset = 0;
9254 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9255 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9256 //                              rsurface.batchtvector3f_bufferoffset = 0;
9257                                 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);
9258                         }
9259                         break;
9260                 case Q3DEFORM_BULGE:
9261                         // deform vertex array to make the surface have moving bulges
9262 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9263 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9264 //                      rsurface.batchvertex3f_bufferoffset = 0;
9265 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9266 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9267 //                      rsurface.batchnormal3f_bufferoffset = 0;
9268                         for (j = 0;j < batchnumvertices;j++)
9269                         {
9270                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9271                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9272                         }
9273                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9274                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9275                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9276                         {
9277 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9278 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9279 //                              rsurface.batchsvector3f_bufferoffset = 0;
9280 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9281 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9282 //                              rsurface.batchtvector3f_bufferoffset = 0;
9283                                 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);
9284                         }
9285                         break;
9286                 case Q3DEFORM_MOVE:
9287                         // deform vertex array
9288                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9289                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9290                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9291                         VectorScale(deform->parms, scale, waveparms);
9292 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9293 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9294 //                      rsurface.batchvertex3f_bufferoffset = 0;
9295                         for (j = 0;j < batchnumvertices;j++)
9296                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9297                         break;
9298                 }
9299         }
9300
9301         // generate texcoords based on the chosen texcoord source
9302         switch(rsurface.texture->tcgen.tcgen)
9303         {
9304         default:
9305         case Q3TCGEN_TEXTURE:
9306                 break;
9307         case Q3TCGEN_LIGHTMAP:
9308 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9309 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9310 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9311                 if (rsurface.batchtexcoordlightmap2f)
9312                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9313                 break;
9314         case Q3TCGEN_VECTOR:
9315 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9316 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9317 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9318                 for (j = 0;j < batchnumvertices;j++)
9319                 {
9320                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9321                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9322                 }
9323                 break;
9324         case Q3TCGEN_ENVIRONMENT:
9325                 // make environment reflections using a spheremap
9326                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9327                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9328                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9329                 for (j = 0;j < batchnumvertices;j++)
9330                 {
9331                         // identical to Q3A's method, but executed in worldspace so
9332                         // carried models can be shiny too
9333
9334                         float viewer[3], d, reflected[3], worldreflected[3];
9335
9336                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9337                         // VectorNormalize(viewer);
9338
9339                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9340
9341                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9342                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9343                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9344                         // note: this is proportinal to viewer, so we can normalize later
9345
9346                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9347                         VectorNormalize(worldreflected);
9348
9349                         // note: this sphere map only uses world x and z!
9350                         // so positive and negative y will LOOK THE SAME.
9351                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9352                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9353                 }
9354                 break;
9355         }
9356         // the only tcmod that needs software vertex processing is turbulent, so
9357         // check for it here and apply the changes if needed
9358         // and we only support that as the first one
9359         // (handling a mixture of turbulent and other tcmods would be problematic
9360         //  without punting it entirely to a software path)
9361         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9362         {
9363                 amplitude = rsurface.texture->tcmods[0].parms[1];
9364                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9365 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9366 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9367 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9368                 for (j = 0;j < batchnumvertices;j++)
9369                 {
9370                         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);
9371                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9372                 }
9373         }
9374
9375         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9376         {
9377                 // convert the modified arrays to vertex structs
9378 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9379 //              rsurface.batchvertexmeshbuffer = NULL;
9380                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9381                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9382                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9383                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9384                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9385                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9386                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9387                 {
9388                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9389                         {
9390                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9391                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9392                         }
9393                 }
9394                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9395                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9396                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9397                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9398                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9399                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9400                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9401                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9402                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9403         }
9404 }
9405
9406 void RSurf_DrawBatch(void)
9407 {
9408         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9409         // through the pipeline, killing it earlier in the pipeline would have
9410         // per-surface overhead rather than per-batch overhead, so it's best to
9411         // reject it here, before it hits glDraw.
9412         if (rsurface.batchnumtriangles == 0)
9413                 return;
9414 #if 0
9415         // batch debugging code
9416         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9417         {
9418                 int i;
9419                 int j;
9420                 int c;
9421                 const int *e;
9422                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9423                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9424                 {
9425                         c = e[i];
9426                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9427                         {
9428                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9429                                 {
9430                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9431                                                 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);
9432                                         break;
9433                                 }
9434                         }
9435                 }
9436         }
9437 #endif
9438         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);
9439 }
9440
9441 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9442 {
9443         // pick the closest matching water plane
9444         int planeindex, vertexindex, bestplaneindex = -1;
9445         float d, bestd;
9446         vec3_t vert;
9447         const float *v;
9448         r_waterstate_waterplane_t *p;
9449         qboolean prepared = false;
9450         bestd = 0;
9451         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9452         {
9453                 if(p->camera_entity != rsurface.texture->camera_entity)
9454                         continue;
9455                 d = 0;
9456                 if(!prepared)
9457                 {
9458                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9459                         prepared = true;
9460                         if(rsurface.batchnumvertices == 0)
9461                                 break;
9462                 }
9463                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9464                 {
9465                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9466                         d += fabs(PlaneDiff(vert, &p->plane));
9467                 }
9468                 if (bestd > d || bestplaneindex < 0)
9469                 {
9470                         bestd = d;
9471                         bestplaneindex = planeindex;
9472                 }
9473         }
9474         return bestplaneindex;
9475         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9476         // this situation though, as it might be better to render single larger
9477         // batches with useless stuff (backface culled for example) than to
9478         // render multiple smaller batches
9479 }
9480
9481 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9482 {
9483         int i;
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;i < rsurface.batchnumvertices;i++)
9488                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9489 }
9490
9491 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9492 {
9493         int i;
9494         float f;
9495         const float *v;
9496         const float *c;
9497         float *c2;
9498         if (rsurface.passcolor4f)
9499         {
9500                 // generate color arrays
9501                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9502                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9503                 rsurface.passcolor4f_vertexbuffer = 0;
9504                 rsurface.passcolor4f_bufferoffset = 0;
9505                 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)
9506                 {
9507                         f = RSurf_FogVertex(v);
9508                         c2[0] = c[0] * f;
9509                         c2[1] = c[1] * f;
9510                         c2[2] = c[2] * f;
9511                         c2[3] = c[3];
9512                 }
9513         }
9514         else
9515         {
9516                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9517                 rsurface.passcolor4f_vertexbuffer = 0;
9518                 rsurface.passcolor4f_bufferoffset = 0;
9519                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9520                 {
9521                         f = RSurf_FogVertex(v);
9522                         c2[0] = f;
9523                         c2[1] = f;
9524                         c2[2] = f;
9525                         c2[3] = 1;
9526                 }
9527         }
9528 }
9529
9530 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9531 {
9532         int i;
9533         float f;
9534         const float *v;
9535         const float *c;
9536         float *c2;
9537         if (!rsurface.passcolor4f)
9538                 return;
9539         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9540         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9541         rsurface.passcolor4f_vertexbuffer = 0;
9542         rsurface.passcolor4f_bufferoffset = 0;
9543         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9544         {
9545                 f = RSurf_FogVertex(v);
9546                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9547                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9548                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9549                 c2[3] = c[3];
9550         }
9551 }
9552
9553 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9554 {
9555         int i;
9556         const float *c;
9557         float *c2;
9558         if (!rsurface.passcolor4f)
9559                 return;
9560         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9561         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9562         rsurface.passcolor4f_vertexbuffer = 0;
9563         rsurface.passcolor4f_bufferoffset = 0;
9564         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9565         {
9566                 c2[0] = c[0] * r;
9567                 c2[1] = c[1] * g;
9568                 c2[2] = c[2] * b;
9569                 c2[3] = c[3] * a;
9570         }
9571 }
9572
9573 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9574 {
9575         int i;
9576         const float *c;
9577         float *c2;
9578         if (!rsurface.passcolor4f)
9579                 return;
9580         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9581         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9582         rsurface.passcolor4f_vertexbuffer = 0;
9583         rsurface.passcolor4f_bufferoffset = 0;
9584         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9585         {
9586                 c2[0] = c[0] + r_refdef.scene.ambient;
9587                 c2[1] = c[1] + r_refdef.scene.ambient;
9588                 c2[2] = c[2] + r_refdef.scene.ambient;
9589                 c2[3] = c[3];
9590         }
9591 }
9592
9593 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9594 {
9595         // TODO: optimize
9596         rsurface.passcolor4f = NULL;
9597         rsurface.passcolor4f_vertexbuffer = 0;
9598         rsurface.passcolor4f_bufferoffset = 0;
9599         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9600         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9601         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9602         GL_Color(r, g, b, a);
9603         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9604         RSurf_DrawBatch();
9605 }
9606
9607 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9608 {
9609         // TODO: optimize applyfog && applycolor case
9610         // just apply fog if necessary, and tint the fog color array if necessary
9611         rsurface.passcolor4f = NULL;
9612         rsurface.passcolor4f_vertexbuffer = 0;
9613         rsurface.passcolor4f_bufferoffset = 0;
9614         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9615         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9616         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9617         GL_Color(r, g, b, a);
9618         RSurf_DrawBatch();
9619 }
9620
9621 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9622 {
9623         // TODO: optimize
9624         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9625         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9626         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9627         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9628         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9629         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9630         GL_Color(r, g, b, a);
9631         RSurf_DrawBatch();
9632 }
9633
9634 static void RSurf_DrawBatch_GL11_ClampColor(void)
9635 {
9636         int i;
9637         const float *c1;
9638         float *c2;
9639         if (!rsurface.passcolor4f)
9640                 return;
9641         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9642         {
9643                 c2[0] = bound(0.0f, c1[0], 1.0f);
9644                 c2[1] = bound(0.0f, c1[1], 1.0f);
9645                 c2[2] = bound(0.0f, c1[2], 1.0f);
9646                 c2[3] = bound(0.0f, c1[3], 1.0f);
9647         }
9648 }
9649
9650 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9651 {
9652         int i;
9653         float f;
9654         const float *v;
9655         const float *n;
9656         float *c;
9657         //vec3_t eyedir;
9658
9659         // fake shading
9660         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9661         rsurface.passcolor4f_vertexbuffer = 0;
9662         rsurface.passcolor4f_bufferoffset = 0;
9663         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)
9664         {
9665                 f = -DotProduct(r_refdef.view.forward, n);
9666                 f = max(0, f);
9667                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9668                 f *= r_refdef.lightmapintensity;
9669                 Vector4Set(c, f, f, f, 1);
9670         }
9671 }
9672
9673 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9674 {
9675         RSurf_DrawBatch_GL11_ApplyFakeLight();
9676         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9677         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9678         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9679         GL_Color(r, g, b, a);
9680         RSurf_DrawBatch();
9681 }
9682
9683 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9684 {
9685         int i;
9686         float f;
9687         float alpha;
9688         const float *v;
9689         const float *n;
9690         float *c;
9691         vec3_t ambientcolor;
9692         vec3_t diffusecolor;
9693         vec3_t lightdir;
9694         // TODO: optimize
9695         // model lighting
9696         VectorCopy(rsurface.modellight_lightdir, lightdir);
9697         f = 0.5f * r_refdef.lightmapintensity;
9698         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9699         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9700         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9701         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9702         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9703         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9704         alpha = *a;
9705         if (VectorLength2(diffusecolor) > 0)
9706         {
9707                 // q3-style directional shading
9708                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9709                 rsurface.passcolor4f_vertexbuffer = 0;
9710                 rsurface.passcolor4f_bufferoffset = 0;
9711                 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)
9712                 {
9713                         if ((f = DotProduct(n, lightdir)) > 0)
9714                                 VectorMA(ambientcolor, f, diffusecolor, c);
9715                         else
9716                                 VectorCopy(ambientcolor, c);
9717                         c[3] = alpha;
9718                 }
9719                 *r = 1;
9720                 *g = 1;
9721                 *b = 1;
9722                 *a = 1;
9723                 *applycolor = false;
9724         }
9725         else
9726         {
9727                 *r = ambientcolor[0];
9728                 *g = ambientcolor[1];
9729                 *b = ambientcolor[2];
9730                 rsurface.passcolor4f = NULL;
9731                 rsurface.passcolor4f_vertexbuffer = 0;
9732                 rsurface.passcolor4f_bufferoffset = 0;
9733         }
9734 }
9735
9736 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9737 {
9738         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9739         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9740         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9741         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9742         GL_Color(r, g, b, a);
9743         RSurf_DrawBatch();
9744 }
9745
9746 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9747 {
9748         int i;
9749         float f;
9750         const float *v;
9751         float *c;
9752
9753         // fake shading
9754         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9755         rsurface.passcolor4f_vertexbuffer = 0;
9756         rsurface.passcolor4f_bufferoffset = 0;
9757
9758         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9759         {
9760                 f = 1 - RSurf_FogVertex(v);
9761                 c[0] = r;
9762                 c[1] = g;
9763                 c[2] = b;
9764                 c[3] = f * a;
9765         }
9766 }
9767
9768 void RSurf_SetupDepthAndCulling(void)
9769 {
9770         // submodels are biased to avoid z-fighting with world surfaces that they
9771         // may be exactly overlapping (avoids z-fighting artifacts on certain
9772         // doors and things in Quake maps)
9773         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9774         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9775         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9776         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9777 }
9778
9779 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9780 {
9781         // transparent sky would be ridiculous
9782         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9783                 return;
9784         R_SetupShader_Generic_NoTexture(false, false);
9785         skyrenderlater = true;
9786         RSurf_SetupDepthAndCulling();
9787         GL_DepthMask(true);
9788         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9789         // skymasking on them, and Quake3 never did sky masking (unlike
9790         // software Quake and software Quake2), so disable the sky masking
9791         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9792         // and skymasking also looks very bad when noclipping outside the
9793         // level, so don't use it then either.
9794         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9795         {
9796                 R_Mesh_ResetTextureState();
9797                 if (skyrendermasked)
9798                 {
9799                         R_SetupShader_DepthOrShadow(false, false);
9800                         // depth-only (masking)
9801                         GL_ColorMask(0,0,0,0);
9802                         // just to make sure that braindead drivers don't draw
9803                         // anything despite that colormask...
9804                         GL_BlendFunc(GL_ZERO, GL_ONE);
9805                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806                         if (rsurface.batchvertex3fbuffer)
9807                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9808                         else
9809                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9810                 }
9811                 else
9812                 {
9813                         R_SetupShader_Generic_NoTexture(false, false);
9814                         // fog sky
9815                         GL_BlendFunc(GL_ONE, GL_ZERO);
9816                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9817                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9818                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9819                 }
9820                 RSurf_DrawBatch();
9821                 if (skyrendermasked)
9822                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9823         }
9824         R_Mesh_ResetTextureState();
9825         GL_Color(1, 1, 1, 1);
9826 }
9827
9828 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9829 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9830 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9831 {
9832         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9833                 return;
9834         if (prepass)
9835         {
9836                 // render screenspace normalmap to texture
9837                 GL_DepthMask(true);
9838                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9839                 RSurf_DrawBatch();
9840                 return;
9841         }
9842
9843         // bind lightmap texture
9844
9845         // water/refraction/reflection/camera surfaces have to be handled specially
9846         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9847         {
9848                 int start, end, startplaneindex;
9849                 for (start = 0;start < texturenumsurfaces;start = end)
9850                 {
9851                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9852                         if(startplaneindex < 0)
9853                         {
9854                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9855                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9856                                 end = start + 1;
9857                                 continue;
9858                         }
9859                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9860                                 ;
9861                         // now that we have a batch using the same planeindex, render it
9862                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9863                         {
9864                                 // render water or distortion background
9865                                 GL_DepthMask(true);
9866                                 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);
9867                                 RSurf_DrawBatch();
9868                                 // blend surface on top
9869                                 GL_DepthMask(false);
9870                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9871                                 RSurf_DrawBatch();
9872                         }
9873                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9874                         {
9875                                 // render surface with reflection texture as input
9876                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9877                                 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);
9878                                 RSurf_DrawBatch();
9879                         }
9880                 }
9881                 return;
9882         }
9883
9884         // render surface batch normally
9885         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9886         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);
9887         RSurf_DrawBatch();
9888 }
9889
9890 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9891 {
9892         // OpenGL 1.3 path - anything not completely ancient
9893         qboolean applycolor;
9894         qboolean applyfog;
9895         int layerindex;
9896         const texturelayer_t *layer;
9897         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);
9898         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9899
9900         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9901         {
9902                 vec4_t layercolor;
9903                 int layertexrgbscale;
9904                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9905                 {
9906                         if (layerindex == 0)
9907                                 GL_AlphaTest(true);
9908                         else
9909                         {
9910                                 GL_AlphaTest(false);
9911                                 GL_DepthFunc(GL_EQUAL);
9912                         }
9913                 }
9914                 GL_DepthMask(layer->depthmask && writedepth);
9915                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9916                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9917                 {
9918                         layertexrgbscale = 4;
9919                         VectorScale(layer->color, 0.25f, layercolor);
9920                 }
9921                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9922                 {
9923                         layertexrgbscale = 2;
9924                         VectorScale(layer->color, 0.5f, layercolor);
9925                 }
9926                 else
9927                 {
9928                         layertexrgbscale = 1;
9929                         VectorScale(layer->color, 1.0f, layercolor);
9930                 }
9931                 layercolor[3] = layer->color[3];
9932                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9933                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9934                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9935                 switch (layer->type)
9936                 {
9937                 case TEXTURELAYERTYPE_LITTEXTURE:
9938                         // single-pass lightmapped texture with 2x rgbscale
9939                         R_Mesh_TexBind(0, r_texture_white);
9940                         R_Mesh_TexMatrix(0, NULL);
9941                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9942                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9943                         R_Mesh_TexBind(1, layer->texture);
9944                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9945                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9946                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9947                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9948                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9949                         else if (FAKELIGHT_ENABLED)
9950                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9951                         else if (rsurface.uselightmaptexture)
9952                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9953                         else
9954                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9955                         break;
9956                 case TEXTURELAYERTYPE_TEXTURE:
9957                         // singletexture unlit texture with transparency support
9958                         R_Mesh_TexBind(0, layer->texture);
9959                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9960                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9961                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9962                         R_Mesh_TexBind(1, 0);
9963                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9964                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9965                         break;
9966                 case TEXTURELAYERTYPE_FOG:
9967                         // singletexture fogging
9968                         if (layer->texture)
9969                         {
9970                                 R_Mesh_TexBind(0, layer->texture);
9971                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9972                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9973                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9974                         }
9975                         else
9976                         {
9977                                 R_Mesh_TexBind(0, 0);
9978                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9979                         }
9980                         R_Mesh_TexBind(1, 0);
9981                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9982                         // generate a color array for the fog pass
9983                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9984                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9985                         RSurf_DrawBatch();
9986                         break;
9987                 default:
9988                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9989                 }
9990         }
9991         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9992         {
9993                 GL_DepthFunc(GL_LEQUAL);
9994                 GL_AlphaTest(false);
9995         }
9996 }
9997
9998 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9999 {
10000         // OpenGL 1.1 - crusty old voodoo path
10001         qboolean applyfog;
10002         int layerindex;
10003         const texturelayer_t *layer;
10004         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);
10005         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10006
10007         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10008         {
10009                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10010                 {
10011                         if (layerindex == 0)
10012                                 GL_AlphaTest(true);
10013                         else
10014                         {
10015                                 GL_AlphaTest(false);
10016                                 GL_DepthFunc(GL_EQUAL);
10017                         }
10018                 }
10019                 GL_DepthMask(layer->depthmask && writedepth);
10020                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10021                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10022                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10023                 switch (layer->type)
10024                 {
10025                 case TEXTURELAYERTYPE_LITTEXTURE:
10026                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10027                         {
10028                                 // two-pass lit texture with 2x rgbscale
10029                                 // first the lightmap pass
10030                                 R_Mesh_TexBind(0, r_texture_white);
10031                                 R_Mesh_TexMatrix(0, NULL);
10032                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10033                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10034                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10035                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10036                                 else if (FAKELIGHT_ENABLED)
10037                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10038                                 else if (rsurface.uselightmaptexture)
10039                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10040                                 else
10041                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10042                                 // then apply the texture to it
10043                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10044                                 R_Mesh_TexBind(0, layer->texture);
10045                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10046                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10047                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10048                                 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 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);
10049                         }
10050                         else
10051                         {
10052                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10053                                 R_Mesh_TexBind(0, layer->texture);
10054                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10055                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10056                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10057                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10058                                         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);
10059                                 else if (FAKELIGHT_ENABLED)
10060                                         RSurf_DrawBatch_GL11_FakeLight(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);
10061                                 else
10062                                         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);
10063                         }
10064                         break;
10065                 case TEXTURELAYERTYPE_TEXTURE:
10066                         // singletexture unlit texture with transparency support
10067                         R_Mesh_TexBind(0, layer->texture);
10068                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10069                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10070                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10071                         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);
10072                         break;
10073                 case TEXTURELAYERTYPE_FOG:
10074                         // singletexture fogging
10075                         if (layer->texture)
10076                         {
10077                                 R_Mesh_TexBind(0, layer->texture);
10078                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10079                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10080                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10081                         }
10082                         else
10083                         {
10084                                 R_Mesh_TexBind(0, 0);
10085                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10086                         }
10087                         // generate a color array for the fog pass
10088                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10089                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10090                         RSurf_DrawBatch();
10091                         break;
10092                 default:
10093                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10094                 }
10095         }
10096         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10097         {
10098                 GL_DepthFunc(GL_LEQUAL);
10099                 GL_AlphaTest(false);
10100         }
10101 }
10102
10103 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10104 {
10105         int vi;
10106         int j;
10107         r_vertexgeneric_t *batchvertex;
10108         float c[4];
10109
10110 //      R_Mesh_ResetTextureState();
10111         R_SetupShader_Generic_NoTexture(false, false);
10112
10113         if(rsurface.texture && rsurface.texture->currentskinframe)
10114         {
10115                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10116                 c[3] *= rsurface.texture->currentalpha;
10117         }
10118         else
10119         {
10120                 c[0] = 1;
10121                 c[1] = 0;
10122                 c[2] = 1;
10123                 c[3] = 1;
10124         }
10125
10126         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10127         {
10128                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10129                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10130                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10131         }
10132
10133         // brighten it up (as texture value 127 means "unlit")
10134         c[0] *= 2 * r_refdef.view.colorscale;
10135         c[1] *= 2 * r_refdef.view.colorscale;
10136         c[2] *= 2 * r_refdef.view.colorscale;
10137
10138         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10139                 c[3] *= r_wateralpha.value;
10140
10141         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10142         {
10143                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10144                 GL_DepthMask(false);
10145         }
10146         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10147         {
10148                 GL_BlendFunc(GL_ONE, GL_ONE);
10149                 GL_DepthMask(false);
10150         }
10151         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10152         {
10153                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10154                 GL_DepthMask(false);
10155         }
10156         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10157         {
10158                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10159                 GL_DepthMask(false);
10160         }
10161         else
10162         {
10163                 GL_BlendFunc(GL_ONE, GL_ZERO);
10164                 GL_DepthMask(writedepth);
10165         }
10166
10167         if (r_showsurfaces.integer == 3)
10168         {
10169                 rsurface.passcolor4f = NULL;
10170
10171                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10172                 {
10173                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10174
10175                         rsurface.passcolor4f = NULL;
10176                         rsurface.passcolor4f_vertexbuffer = 0;
10177                         rsurface.passcolor4f_bufferoffset = 0;
10178                 }
10179                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10180                 {
10181                         qboolean applycolor = true;
10182                         float one = 1.0;
10183
10184                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10185
10186                         r_refdef.lightmapintensity = 1;
10187                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10188                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10189                 }
10190                 else if (FAKELIGHT_ENABLED)
10191                 {
10192                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10193
10194                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10195                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10196                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10197                 }
10198                 else
10199                 {
10200                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10201
10202                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10203                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10204                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10205                 }
10206
10207                 if(!rsurface.passcolor4f)
10208                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10209
10210                 RSurf_DrawBatch_GL11_ApplyAmbient();
10211                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10212                 if(r_refdef.fogenabled)
10213                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10214                 RSurf_DrawBatch_GL11_ClampColor();
10215
10216                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10217                 R_SetupShader_Generic_NoTexture(false, false);
10218                 RSurf_DrawBatch();
10219         }
10220         else if (!r_refdef.view.showdebug)
10221         {
10222                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10223                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10224                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10225                 {
10226                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10227                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10228                 }
10229                 R_Mesh_PrepareVertices_Generic_Unlock();
10230                 RSurf_DrawBatch();
10231         }
10232         else if (r_showsurfaces.integer == 4)
10233         {
10234                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10235                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10236                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10237                 {
10238                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10239                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10240                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10241                 }
10242                 R_Mesh_PrepareVertices_Generic_Unlock();
10243                 RSurf_DrawBatch();
10244         }
10245         else if (r_showsurfaces.integer == 2)
10246         {
10247                 const int *e;
10248                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10249                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10250                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10251                 {
10252                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10253                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10254                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10255                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10256                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10257                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10258                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10259                 }
10260                 R_Mesh_PrepareVertices_Generic_Unlock();
10261                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10262         }
10263         else
10264         {
10265                 int texturesurfaceindex;
10266                 int k;
10267                 const msurface_t *surface;
10268                 float surfacecolor4f[4];
10269                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10270                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10271                 vi = 0;
10272                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10273                 {
10274                         surface = texturesurfacelist[texturesurfaceindex];
10275                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10276                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10277                         for (j = 0;j < surface->num_vertices;j++)
10278                         {
10279                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10280                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10281                                 vi++;
10282                         }
10283                 }
10284                 R_Mesh_PrepareVertices_Generic_Unlock();
10285                 RSurf_DrawBatch();
10286         }
10287 }
10288
10289 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10290 {
10291         CHECKGLERROR
10292         RSurf_SetupDepthAndCulling();
10293         if (r_showsurfaces.integer)
10294         {
10295                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10296                 return;
10297         }
10298         switch (vid.renderpath)
10299         {
10300         case RENDERPATH_GL20:
10301         case RENDERPATH_D3D9:
10302         case RENDERPATH_D3D10:
10303         case RENDERPATH_D3D11:
10304         case RENDERPATH_SOFT:
10305         case RENDERPATH_GLES2:
10306                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10307                 break;
10308         case RENDERPATH_GL13:
10309         case RENDERPATH_GLES1:
10310                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10311                 break;
10312         case RENDERPATH_GL11:
10313                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10314                 break;
10315         }
10316         CHECKGLERROR
10317 }
10318
10319 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10320 {
10321         CHECKGLERROR
10322         RSurf_SetupDepthAndCulling();
10323         if (r_showsurfaces.integer)
10324         {
10325                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10326                 return;
10327         }
10328         switch (vid.renderpath)
10329         {
10330         case RENDERPATH_GL20:
10331         case RENDERPATH_D3D9:
10332         case RENDERPATH_D3D10:
10333         case RENDERPATH_D3D11:
10334         case RENDERPATH_SOFT:
10335         case RENDERPATH_GLES2:
10336                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10337                 break;
10338         case RENDERPATH_GL13:
10339         case RENDERPATH_GLES1:
10340                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10341                 break;
10342         case RENDERPATH_GL11:
10343                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10344                 break;
10345         }
10346         CHECKGLERROR
10347 }
10348
10349 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10350 {
10351         int i, j;
10352         int texturenumsurfaces, endsurface;
10353         texture_t *texture;
10354         const msurface_t *surface;
10355         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10356
10357         // if the model is static it doesn't matter what value we give for
10358         // wantnormals and wanttangents, so this logic uses only rules applicable
10359         // to a model, knowing that they are meaningless otherwise
10360         if (ent == r_refdef.scene.worldentity)
10361                 RSurf_ActiveWorldEntity();
10362         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10363                 RSurf_ActiveModelEntity(ent, false, false, false);
10364         else
10365         {
10366                 switch (vid.renderpath)
10367                 {
10368                 case RENDERPATH_GL20:
10369                 case RENDERPATH_D3D9:
10370                 case RENDERPATH_D3D10:
10371                 case RENDERPATH_D3D11:
10372                 case RENDERPATH_SOFT:
10373                 case RENDERPATH_GLES2:
10374                         RSurf_ActiveModelEntity(ent, true, true, false);
10375                         break;
10376                 case RENDERPATH_GL11:
10377                 case RENDERPATH_GL13:
10378                 case RENDERPATH_GLES1:
10379                         RSurf_ActiveModelEntity(ent, true, false, false);
10380                         break;
10381                 }
10382         }
10383
10384         if (r_transparentdepthmasking.integer)
10385         {
10386                 qboolean setup = false;
10387                 for (i = 0;i < numsurfaces;i = j)
10388                 {
10389                         j = i + 1;
10390                         surface = rsurface.modelsurfaces + surfacelist[i];
10391                         texture = surface->texture;
10392                         rsurface.texture = R_GetCurrentTexture(texture);
10393                         rsurface.lightmaptexture = NULL;
10394                         rsurface.deluxemaptexture = NULL;
10395                         rsurface.uselightmaptexture = false;
10396                         // scan ahead until we find a different texture
10397                         endsurface = min(i + 1024, numsurfaces);
10398                         texturenumsurfaces = 0;
10399                         texturesurfacelist[texturenumsurfaces++] = surface;
10400                         for (;j < endsurface;j++)
10401                         {
10402                                 surface = rsurface.modelsurfaces + surfacelist[j];
10403                                 if (texture != surface->texture)
10404                                         break;
10405                                 texturesurfacelist[texturenumsurfaces++] = surface;
10406                         }
10407                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10408                                 continue;
10409                         // render the range of surfaces as depth
10410                         if (!setup)
10411                         {
10412                                 setup = true;
10413                                 GL_ColorMask(0,0,0,0);
10414                                 GL_Color(1,1,1,1);
10415                                 GL_DepthTest(true);
10416                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10417                                 GL_DepthMask(true);
10418 //                              R_Mesh_ResetTextureState();
10419                                 R_SetupShader_DepthOrShadow(false, false);
10420                         }
10421                         RSurf_SetupDepthAndCulling();
10422                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10423                         if (rsurface.batchvertex3fbuffer)
10424                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10425                         else
10426                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10427                         RSurf_DrawBatch();
10428                 }
10429                 if (setup)
10430                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10431         }
10432
10433         for (i = 0;i < numsurfaces;i = j)
10434         {
10435                 j = i + 1;
10436                 surface = rsurface.modelsurfaces + surfacelist[i];
10437                 texture = surface->texture;
10438                 rsurface.texture = R_GetCurrentTexture(texture);
10439                 // scan ahead until we find a different texture
10440                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10441                 texturenumsurfaces = 0;
10442                 texturesurfacelist[texturenumsurfaces++] = surface;
10443                 if(FAKELIGHT_ENABLED)
10444                 {
10445                         rsurface.lightmaptexture = NULL;
10446                         rsurface.deluxemaptexture = NULL;
10447                         rsurface.uselightmaptexture = false;
10448                         for (;j < endsurface;j++)
10449                         {
10450                                 surface = rsurface.modelsurfaces + surfacelist[j];
10451                                 if (texture != surface->texture)
10452                                         break;
10453                                 texturesurfacelist[texturenumsurfaces++] = surface;
10454                         }
10455                 }
10456                 else
10457                 {
10458                         rsurface.lightmaptexture = surface->lightmaptexture;
10459                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10460                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10461                         for (;j < endsurface;j++)
10462                         {
10463                                 surface = rsurface.modelsurfaces + surfacelist[j];
10464                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10465                                         break;
10466                                 texturesurfacelist[texturenumsurfaces++] = surface;
10467                         }
10468                 }
10469                 // render the range of surfaces
10470                 if (ent == r_refdef.scene.worldentity)
10471                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10472                 else
10473                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10474         }
10475         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10476 }
10477
10478 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10479 {
10480         // transparent surfaces get pushed off into the transparent queue
10481         int surfacelistindex;
10482         const msurface_t *surface;
10483         vec3_t tempcenter, center;
10484         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10485         {
10486                 surface = texturesurfacelist[surfacelistindex];
10487                 if (r_transparent_sortsurfacesbynearest.integer)
10488                 {
10489                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10490                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10491                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10492                 }
10493                 else
10494                 {
10495                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10496                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10497                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10498                 }
10499                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10500                 if (rsurface.entity->transparent_offset) // transparent offset
10501                 {
10502                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10503                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10504                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10505                 }
10506                 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10507         }
10508 }
10509
10510 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10511 {
10512         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10513                 return;
10514         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10515                 return;
10516         RSurf_SetupDepthAndCulling();
10517         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10518         if (rsurface.batchvertex3fbuffer)
10519                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10520         else
10521                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10522         RSurf_DrawBatch();
10523 }
10524
10525 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10526 {
10527         CHECKGLERROR
10528         if (depthonly)
10529                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10530         else if (prepass)
10531         {
10532                 if (!rsurface.texture->currentnumlayers)
10533                         return;
10534                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10535                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10536                 else
10537                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10538         }
10539         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10540                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10541         else if (!rsurface.texture->currentnumlayers)
10542                 return;
10543         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10544         {
10545                 // in the deferred case, transparent surfaces were queued during prepass
10546                 if (!r_shadow_usingdeferredprepass)
10547                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10548         }
10549         else
10550         {
10551                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10552                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10553         }
10554         CHECKGLERROR
10555 }
10556
10557 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10558 {
10559         int i, j;
10560         texture_t *texture;
10561         R_FrameData_SetMark();
10562         // break the surface list down into batches by texture and use of lightmapping
10563         for (i = 0;i < numsurfaces;i = j)
10564         {
10565                 j = i + 1;
10566                 // texture is the base texture pointer, rsurface.texture is the
10567                 // current frame/skin the texture is directing us to use (for example
10568                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10569                 // use skin 1 instead)
10570                 texture = surfacelist[i]->texture;
10571                 rsurface.texture = R_GetCurrentTexture(texture);
10572                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10573                 {
10574                         // if this texture is not the kind we want, skip ahead to the next one
10575                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10576                                 ;
10577                         continue;
10578                 }
10579                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10580                 {
10581                         rsurface.lightmaptexture = NULL;
10582                         rsurface.deluxemaptexture = NULL;
10583                         rsurface.uselightmaptexture = false;
10584                         // simply scan ahead until we find a different texture or lightmap state
10585                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10586                                 ;
10587                 }
10588                 else
10589                 {
10590                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10591                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10592                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10593                         // simply scan ahead until we find a different texture or lightmap state
10594                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10595                                 ;
10596                 }
10597                 // render the range of surfaces
10598                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10599         }
10600         R_FrameData_ReturnToMark();
10601 }
10602
10603 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10604 {
10605         CHECKGLERROR
10606         if (depthonly)
10607                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10608         else if (prepass)
10609         {
10610                 if (!rsurface.texture->currentnumlayers)
10611                         return;
10612                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10613                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10614                 else
10615                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10616         }
10617         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10618                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10619         else if (!rsurface.texture->currentnumlayers)
10620                 return;
10621         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10622         {
10623                 // in the deferred case, transparent surfaces were queued during prepass
10624                 if (!r_shadow_usingdeferredprepass)
10625                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10626         }
10627         else
10628         {
10629                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10630                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10631         }
10632         CHECKGLERROR
10633 }
10634
10635 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10636 {
10637         int i, j;
10638         texture_t *texture;
10639         R_FrameData_SetMark();
10640         // break the surface list down into batches by texture and use of lightmapping
10641         for (i = 0;i < numsurfaces;i = j)
10642         {
10643                 j = i + 1;
10644                 // texture is the base texture pointer, rsurface.texture is the
10645                 // current frame/skin the texture is directing us to use (for example
10646                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10647                 // use skin 1 instead)
10648                 texture = surfacelist[i]->texture;
10649                 rsurface.texture = R_GetCurrentTexture(texture);
10650                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10651                 {
10652                         // if this texture is not the kind we want, skip ahead to the next one
10653                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10654                                 ;
10655                         continue;
10656                 }
10657                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10658                 {
10659                         rsurface.lightmaptexture = NULL;
10660                         rsurface.deluxemaptexture = NULL;
10661                         rsurface.uselightmaptexture = false;
10662                         // simply scan ahead until we find a different texture or lightmap state
10663                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10664                                 ;
10665                 }
10666                 else
10667                 {
10668                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10669                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10670                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10671                         // simply scan ahead until we find a different texture or lightmap state
10672                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10673                                 ;
10674                 }
10675                 // render the range of surfaces
10676                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10677         }
10678         R_FrameData_ReturnToMark();
10679 }
10680
10681 float locboxvertex3f[6*4*3] =
10682 {
10683         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10684         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10685         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10686         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10687         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10688         1,0,0, 0,0,0, 0,1,0, 1,1,0
10689 };
10690
10691 unsigned short locboxelements[6*2*3] =
10692 {
10693          0, 1, 2, 0, 2, 3,
10694          4, 5, 6, 4, 6, 7,
10695          8, 9,10, 8,10,11,
10696         12,13,14, 12,14,15,
10697         16,17,18, 16,18,19,
10698         20,21,22, 20,22,23
10699 };
10700
10701 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10702 {
10703         int i, j;
10704         cl_locnode_t *loc = (cl_locnode_t *)ent;
10705         vec3_t mins, size;
10706         float vertex3f[6*4*3];
10707         CHECKGLERROR
10708         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10709         GL_DepthMask(false);
10710         GL_DepthRange(0, 1);
10711         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10712         GL_DepthTest(true);
10713         GL_CullFace(GL_NONE);
10714         R_EntityMatrix(&identitymatrix);
10715
10716 //      R_Mesh_ResetTextureState();
10717
10718         i = surfacelist[0];
10719         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10720                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10721                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10722                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10723
10724         if (VectorCompare(loc->mins, loc->maxs))
10725         {
10726                 VectorSet(size, 2, 2, 2);
10727                 VectorMA(loc->mins, -0.5f, size, mins);
10728         }
10729         else
10730         {
10731                 VectorCopy(loc->mins, mins);
10732                 VectorSubtract(loc->maxs, loc->mins, size);
10733         }
10734
10735         for (i = 0;i < 6*4*3;)
10736                 for (j = 0;j < 3;j++, i++)
10737                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10738
10739         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10740         R_SetupShader_Generic_NoTexture(false, false);
10741         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10742 }
10743
10744 void R_DrawLocs(void)
10745 {
10746         int index;
10747         cl_locnode_t *loc, *nearestloc;
10748         vec3_t center;
10749         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10750         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10751         {
10752                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10753                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10754         }
10755 }
10756
10757 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10758 {
10759         if (decalsystem->decals)
10760                 Mem_Free(decalsystem->decals);
10761         memset(decalsystem, 0, sizeof(*decalsystem));
10762 }
10763
10764 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)
10765 {
10766         tridecal_t *decal;
10767         tridecal_t *decals;
10768         int i;
10769
10770         // expand or initialize the system
10771         if (decalsystem->maxdecals <= decalsystem->numdecals)
10772         {
10773                 decalsystem_t old = *decalsystem;
10774                 qboolean useshortelements;
10775                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10776                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10777                 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)));
10778                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10779                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10780                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10781                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10782                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10783                 if (decalsystem->numdecals)
10784                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10785                 if (old.decals)
10786                         Mem_Free(old.decals);
10787                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10788                         decalsystem->element3i[i] = i;
10789                 if (useshortelements)
10790                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10791                                 decalsystem->element3s[i] = i;
10792         }
10793
10794         // grab a decal and search for another free slot for the next one
10795         decals = decalsystem->decals;
10796         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10797         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10798                 ;
10799         decalsystem->freedecal = i;
10800         if (decalsystem->numdecals <= i)
10801                 decalsystem->numdecals = i + 1;
10802
10803         // initialize the decal
10804         decal->lived = 0;
10805         decal->triangleindex = triangleindex;
10806         decal->surfaceindex = surfaceindex;
10807         decal->decalsequence = decalsequence;
10808         decal->color4f[0][0] = c0[0];
10809         decal->color4f[0][1] = c0[1];
10810         decal->color4f[0][2] = c0[2];
10811         decal->color4f[0][3] = 1;
10812         decal->color4f[1][0] = c1[0];
10813         decal->color4f[1][1] = c1[1];
10814         decal->color4f[1][2] = c1[2];
10815         decal->color4f[1][3] = 1;
10816         decal->color4f[2][0] = c2[0];
10817         decal->color4f[2][1] = c2[1];
10818         decal->color4f[2][2] = c2[2];
10819         decal->color4f[2][3] = 1;
10820         decal->vertex3f[0][0] = v0[0];
10821         decal->vertex3f[0][1] = v0[1];
10822         decal->vertex3f[0][2] = v0[2];
10823         decal->vertex3f[1][0] = v1[0];
10824         decal->vertex3f[1][1] = v1[1];
10825         decal->vertex3f[1][2] = v1[2];
10826         decal->vertex3f[2][0] = v2[0];
10827         decal->vertex3f[2][1] = v2[1];
10828         decal->vertex3f[2][2] = v2[2];
10829         decal->texcoord2f[0][0] = t0[0];
10830         decal->texcoord2f[0][1] = t0[1];
10831         decal->texcoord2f[1][0] = t1[0];
10832         decal->texcoord2f[1][1] = t1[1];
10833         decal->texcoord2f[2][0] = t2[0];
10834         decal->texcoord2f[2][1] = t2[1];
10835         TriangleNormal(v0, v1, v2, decal->plane);
10836         VectorNormalize(decal->plane);
10837         decal->plane[3] = DotProduct(v0, decal->plane);
10838 }
10839
10840 extern cvar_t cl_decals_bias;
10841 extern cvar_t cl_decals_models;
10842 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10843 // baseparms, parms, temps
10844 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)
10845 {
10846         int cornerindex;
10847         int index;
10848         float v[9][3];
10849         const float *vertex3f;
10850         const float *normal3f;
10851         int numpoints;
10852         float points[2][9][3];
10853         float temp[3];
10854         float tc[9][2];
10855         float f;
10856         float c[9][4];
10857         const int *e;
10858
10859         e = rsurface.modelelement3i + 3*triangleindex;
10860
10861         vertex3f = rsurface.modelvertex3f;
10862         normal3f = rsurface.modelnormal3f;
10863
10864         if (normal3f)
10865         {
10866                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10867                 {
10868                         index = 3*e[cornerindex];
10869                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10870                 }
10871         }
10872         else
10873         {
10874                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10875                 {
10876                         index = 3*e[cornerindex];
10877                         VectorCopy(vertex3f + index, v[cornerindex]);
10878                 }
10879         }
10880
10881         // cull backfaces
10882         //TriangleNormal(v[0], v[1], v[2], normal);
10883         //if (DotProduct(normal, localnormal) < 0.0f)
10884         //      continue;
10885         // clip by each of the box planes formed from the projection matrix
10886         // if anything survives, we emit the decal
10887         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]);
10888         if (numpoints < 3)
10889                 return;
10890         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]);
10891         if (numpoints < 3)
10892                 return;
10893         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]);
10894         if (numpoints < 3)
10895                 return;
10896         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]);
10897         if (numpoints < 3)
10898                 return;
10899         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]);
10900         if (numpoints < 3)
10901                 return;
10902         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]);
10903         if (numpoints < 3)
10904                 return;
10905         // some part of the triangle survived, so we have to accept it...
10906         if (dynamic)
10907         {
10908                 // dynamic always uses the original triangle
10909                 numpoints = 3;
10910                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10911                 {
10912                         index = 3*e[cornerindex];
10913                         VectorCopy(vertex3f + index, v[cornerindex]);
10914                 }
10915         }
10916         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10917         {
10918                 // convert vertex positions to texcoords
10919                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10920                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10921                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10922                 // calculate distance fade from the projection origin
10923                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10924                 f = bound(0.0f, f, 1.0f);
10925                 c[cornerindex][0] = r * f;
10926                 c[cornerindex][1] = g * f;
10927                 c[cornerindex][2] = b * f;
10928                 c[cornerindex][3] = 1.0f;
10929                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10930         }
10931         if (dynamic)
10932                 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);
10933         else
10934                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10935                         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);
10936 }
10937 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)
10938 {
10939         matrix4x4_t projection;
10940         decalsystem_t *decalsystem;
10941         qboolean dynamic;
10942         dp_model_t *model;
10943         const msurface_t *surface;
10944         const msurface_t *surfaces;
10945         const int *surfacelist;
10946         const texture_t *texture;
10947         int numtriangles;
10948         int numsurfacelist;
10949         int surfacelistindex;
10950         int surfaceindex;
10951         int triangleindex;
10952         float localorigin[3];
10953         float localnormal[3];
10954         float localmins[3];
10955         float localmaxs[3];
10956         float localsize;
10957         //float normal[3];
10958         float planes[6][4];
10959         float angles[3];
10960         bih_t *bih;
10961         int bih_triangles_count;
10962         int bih_triangles[256];
10963         int bih_surfaces[256];
10964
10965         decalsystem = &ent->decalsystem;
10966         model = ent->model;
10967         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10968         {
10969                 R_DecalSystem_Reset(&ent->decalsystem);
10970                 return;
10971         }
10972
10973         if (!model->brush.data_leafs && !cl_decals_models.integer)
10974         {
10975                 if (decalsystem->model)
10976                         R_DecalSystem_Reset(decalsystem);
10977                 return;
10978         }
10979
10980         if (decalsystem->model != model)
10981                 R_DecalSystem_Reset(decalsystem);
10982         decalsystem->model = model;
10983
10984         RSurf_ActiveModelEntity(ent, true, false, false);
10985
10986         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10987         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10988         VectorNormalize(localnormal);
10989         localsize = worldsize*rsurface.inversematrixscale;
10990         localmins[0] = localorigin[0] - localsize;
10991         localmins[1] = localorigin[1] - localsize;
10992         localmins[2] = localorigin[2] - localsize;
10993         localmaxs[0] = localorigin[0] + localsize;
10994         localmaxs[1] = localorigin[1] + localsize;
10995         localmaxs[2] = localorigin[2] + localsize;
10996
10997         //VectorCopy(localnormal, planes[4]);
10998         //VectorVectors(planes[4], planes[2], planes[0]);
10999         AnglesFromVectors(angles, localnormal, NULL, false);
11000         AngleVectors(angles, planes[0], planes[2], planes[4]);
11001         VectorNegate(planes[0], planes[1]);
11002         VectorNegate(planes[2], planes[3]);
11003         VectorNegate(planes[4], planes[5]);
11004         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11005         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11006         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11007         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11008         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11009         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11010
11011 #if 1
11012 // works
11013 {
11014         matrix4x4_t forwardprojection;
11015         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11016         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11017 }
11018 #else
11019 // broken
11020 {
11021         float projectionvector[4][3];
11022         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11023         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11024         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11025         projectionvector[0][0] = planes[0][0] * ilocalsize;
11026         projectionvector[0][1] = planes[1][0] * ilocalsize;
11027         projectionvector[0][2] = planes[2][0] * ilocalsize;
11028         projectionvector[1][0] = planes[0][1] * ilocalsize;
11029         projectionvector[1][1] = planes[1][1] * ilocalsize;
11030         projectionvector[1][2] = planes[2][1] * ilocalsize;
11031         projectionvector[2][0] = planes[0][2] * ilocalsize;
11032         projectionvector[2][1] = planes[1][2] * ilocalsize;
11033         projectionvector[2][2] = planes[2][2] * ilocalsize;
11034         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11035         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11036         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11037         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11038 }
11039 #endif
11040
11041         dynamic = model->surfmesh.isanimated;
11042         numsurfacelist = model->nummodelsurfaces;
11043         surfacelist = model->sortedmodelsurfaces;
11044         surfaces = model->data_surfaces;
11045
11046         bih = NULL;
11047         bih_triangles_count = -1;
11048         if(!dynamic)
11049         {
11050                 if(model->render_bih.numleafs)
11051                         bih = &model->render_bih;
11052                 else if(model->collision_bih.numleafs)
11053                         bih = &model->collision_bih;
11054         }
11055         if(bih)
11056                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11057         if(bih_triangles_count == 0)
11058                 return;
11059         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11060                 return;
11061         if(bih_triangles_count > 0)
11062         {
11063                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11064                 {
11065                         surfaceindex = bih_surfaces[triangleindex];
11066                         surface = surfaces + surfaceindex;
11067                         texture = surface->texture;
11068                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11069                                 continue;
11070                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11071                                 continue;
11072                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11073                 }
11074         }
11075         else
11076         {
11077                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11078                 {
11079                         surfaceindex = surfacelist[surfacelistindex];
11080                         surface = surfaces + surfaceindex;
11081                         // check cull box first because it rejects more than any other check
11082                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11083                                 continue;
11084                         // skip transparent surfaces
11085                         texture = surface->texture;
11086                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11087                                 continue;
11088                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11089                                 continue;
11090                         numtriangles = surface->num_triangles;
11091                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11092                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11093                 }
11094         }
11095 }
11096
11097 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11098 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)
11099 {
11100         int renderentityindex;
11101         float worldmins[3];
11102         float worldmaxs[3];
11103         entity_render_t *ent;
11104
11105         if (!cl_decals_newsystem.integer)
11106                 return;
11107
11108         worldmins[0] = worldorigin[0] - worldsize;
11109         worldmins[1] = worldorigin[1] - worldsize;
11110         worldmins[2] = worldorigin[2] - worldsize;
11111         worldmaxs[0] = worldorigin[0] + worldsize;
11112         worldmaxs[1] = worldorigin[1] + worldsize;
11113         worldmaxs[2] = worldorigin[2] + worldsize;
11114
11115         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11116
11117         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11118         {
11119                 ent = r_refdef.scene.entities[renderentityindex];
11120                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11121                         continue;
11122
11123                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11124         }
11125 }
11126
11127 typedef struct r_decalsystem_splatqueue_s
11128 {
11129         vec3_t worldorigin;
11130         vec3_t worldnormal;
11131         float color[4];
11132         float tcrange[4];
11133         float worldsize;
11134         int decalsequence;
11135 }
11136 r_decalsystem_splatqueue_t;
11137
11138 int r_decalsystem_numqueued = 0;
11139 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11140
11141 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)
11142 {
11143         r_decalsystem_splatqueue_t *queue;
11144
11145         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11146                 return;
11147
11148         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11149         VectorCopy(worldorigin, queue->worldorigin);
11150         VectorCopy(worldnormal, queue->worldnormal);
11151         Vector4Set(queue->color, r, g, b, a);
11152         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11153         queue->worldsize = worldsize;
11154         queue->decalsequence = cl.decalsequence++;
11155 }
11156
11157 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11158 {
11159         int i;
11160         r_decalsystem_splatqueue_t *queue;
11161
11162         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11163                 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);
11164         r_decalsystem_numqueued = 0;
11165 }
11166
11167 extern cvar_t cl_decals_max;
11168 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11169 {
11170         int i;
11171         decalsystem_t *decalsystem = &ent->decalsystem;
11172         int numdecals;
11173         int killsequence;
11174         tridecal_t *decal;
11175         float frametime;
11176         float lifetime;
11177
11178         if (!decalsystem->numdecals)
11179                 return;
11180
11181         if (r_showsurfaces.integer)
11182                 return;
11183
11184         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11185         {
11186                 R_DecalSystem_Reset(decalsystem);
11187                 return;
11188         }
11189
11190         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11191         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11192
11193         if (decalsystem->lastupdatetime)
11194                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11195         else
11196                 frametime = 0;
11197         decalsystem->lastupdatetime = r_refdef.scene.time;
11198         numdecals = decalsystem->numdecals;
11199
11200         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11201         {
11202                 if (decal->color4f[0][3])
11203                 {
11204                         decal->lived += frametime;
11205                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11206                         {
11207                                 memset(decal, 0, sizeof(*decal));
11208                                 if (decalsystem->freedecal > i)
11209                                         decalsystem->freedecal = i;
11210                         }
11211                 }
11212         }
11213         decal = decalsystem->decals;
11214         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11215                 numdecals--;
11216
11217         // collapse the array by shuffling the tail decals into the gaps
11218         for (;;)
11219         {
11220                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11221                         decalsystem->freedecal++;
11222                 if (decalsystem->freedecal == numdecals)
11223                         break;
11224                 decal[decalsystem->freedecal] = decal[--numdecals];
11225         }
11226
11227         decalsystem->numdecals = numdecals;
11228
11229         if (numdecals <= 0)
11230         {
11231                 // if there are no decals left, reset decalsystem
11232                 R_DecalSystem_Reset(decalsystem);
11233         }
11234 }
11235
11236 extern skinframe_t *decalskinframe;
11237 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11238 {
11239         int i;
11240         decalsystem_t *decalsystem = &ent->decalsystem;
11241         int numdecals;
11242         tridecal_t *decal;
11243         float faderate;
11244         float alpha;
11245         float *v3f;
11246         float *c4f;
11247         float *t2f;
11248         const int *e;
11249         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11250         int numtris = 0;
11251
11252         numdecals = decalsystem->numdecals;
11253         if (!numdecals)
11254                 return;
11255
11256         if (r_showsurfaces.integer)
11257                 return;
11258
11259         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11260         {
11261                 R_DecalSystem_Reset(decalsystem);
11262                 return;
11263         }
11264
11265         // if the model is static it doesn't matter what value we give for
11266         // wantnormals and wanttangents, so this logic uses only rules applicable
11267         // to a model, knowing that they are meaningless otherwise
11268         if (ent == r_refdef.scene.worldentity)
11269                 RSurf_ActiveWorldEntity();
11270         else
11271                 RSurf_ActiveModelEntity(ent, false, false, false);
11272
11273         decalsystem->lastupdatetime = r_refdef.scene.time;
11274
11275         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11276
11277         // update vertex positions for animated models
11278         v3f = decalsystem->vertex3f;
11279         c4f = decalsystem->color4f;
11280         t2f = decalsystem->texcoord2f;
11281         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11282         {
11283                 if (!decal->color4f[0][3])
11284                         continue;
11285
11286                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11287                         continue;
11288
11289                 // skip backfaces
11290                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11291                         continue;
11292
11293                 // update color values for fading decals
11294                 if (decal->lived >= cl_decals_time.value)
11295                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11296                 else
11297                         alpha = 1.0f;
11298
11299                 c4f[ 0] = decal->color4f[0][0] * alpha;
11300                 c4f[ 1] = decal->color4f[0][1] * alpha;
11301                 c4f[ 2] = decal->color4f[0][2] * alpha;
11302                 c4f[ 3] = 1;
11303                 c4f[ 4] = decal->color4f[1][0] * alpha;
11304                 c4f[ 5] = decal->color4f[1][1] * alpha;
11305                 c4f[ 6] = decal->color4f[1][2] * alpha;
11306                 c4f[ 7] = 1;
11307                 c4f[ 8] = decal->color4f[2][0] * alpha;
11308                 c4f[ 9] = decal->color4f[2][1] * alpha;
11309                 c4f[10] = decal->color4f[2][2] * alpha;
11310                 c4f[11] = 1;
11311
11312                 t2f[0] = decal->texcoord2f[0][0];
11313                 t2f[1] = decal->texcoord2f[0][1];
11314                 t2f[2] = decal->texcoord2f[1][0];
11315                 t2f[3] = decal->texcoord2f[1][1];
11316                 t2f[4] = decal->texcoord2f[2][0];
11317                 t2f[5] = decal->texcoord2f[2][1];
11318
11319                 // update vertex positions for animated models
11320                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11321                 {
11322                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11323                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11324                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11325                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11326                 }
11327                 else
11328                 {
11329                         VectorCopy(decal->vertex3f[0], v3f);
11330                         VectorCopy(decal->vertex3f[1], v3f + 3);
11331                         VectorCopy(decal->vertex3f[2], v3f + 6);
11332                 }
11333
11334                 if (r_refdef.fogenabled)
11335                 {
11336                         alpha = RSurf_FogVertex(v3f);
11337                         VectorScale(c4f, alpha, c4f);
11338                         alpha = RSurf_FogVertex(v3f + 3);
11339                         VectorScale(c4f + 4, alpha, c4f + 4);
11340                         alpha = RSurf_FogVertex(v3f + 6);
11341                         VectorScale(c4f + 8, alpha, c4f + 8);
11342                 }
11343
11344                 v3f += 9;
11345                 c4f += 12;
11346                 t2f += 6;
11347                 numtris++;
11348         }
11349
11350         if (numtris > 0)
11351         {
11352                 r_refdef.stats.drawndecals += numtris;
11353
11354                 // now render the decals all at once
11355                 // (this assumes they all use one particle font texture!)
11356                 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);
11357 //              R_Mesh_ResetTextureState();
11358                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11359                 GL_DepthMask(false);
11360                 GL_DepthRange(0, 1);
11361                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11362                 GL_DepthTest(true);
11363                 GL_CullFace(GL_NONE);
11364                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11365                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11366                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11367         }
11368 }
11369
11370 static void R_DrawModelDecals(void)
11371 {
11372         int i, numdecals;
11373
11374         // fade faster when there are too many decals
11375         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11376         for (i = 0;i < r_refdef.scene.numentities;i++)
11377                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11378
11379         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11380         for (i = 0;i < r_refdef.scene.numentities;i++)
11381                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11382                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11383
11384         R_DecalSystem_ApplySplatEntitiesQueue();
11385
11386         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11387         for (i = 0;i < r_refdef.scene.numentities;i++)
11388                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11389
11390         r_refdef.stats.totaldecals += numdecals;
11391
11392         if (r_showsurfaces.integer)
11393                 return;
11394
11395         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11396
11397         for (i = 0;i < r_refdef.scene.numentities;i++)
11398         {
11399                 if (!r_refdef.viewcache.entityvisible[i])
11400                         continue;
11401                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11402                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11403         }
11404 }
11405
11406 extern cvar_t mod_collision_bih;
11407 static void R_DrawDebugModel(void)
11408 {
11409         entity_render_t *ent = rsurface.entity;
11410         int i, j, k, l, flagsmask;
11411         const msurface_t *surface;
11412         dp_model_t *model = ent->model;
11413         vec3_t v;
11414
11415         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11416                 return;
11417
11418         if (r_showoverdraw.value > 0)
11419         {
11420                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11421                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11422                 R_SetupShader_Generic_NoTexture(false, false);
11423                 GL_DepthTest(false);
11424                 GL_DepthMask(false);
11425                 GL_DepthRange(0, 1);
11426                 GL_BlendFunc(GL_ONE, GL_ONE);
11427                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11428                 {
11429                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11430                                 continue;
11431                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11432                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11433                         {
11434                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11435                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11436                                 if (!rsurface.texture->currentlayers->depthmask)
11437                                         GL_Color(c, 0, 0, 1.0f);
11438                                 else if (ent == r_refdef.scene.worldentity)
11439                                         GL_Color(c, c, c, 1.0f);
11440                                 else
11441                                         GL_Color(0, c, 0, 1.0f);
11442                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11443                                 RSurf_DrawBatch();
11444                         }
11445                 }
11446                 rsurface.texture = NULL;
11447         }
11448
11449         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11450
11451 //      R_Mesh_ResetTextureState();
11452         R_SetupShader_Generic_NoTexture(false, false);
11453         GL_DepthRange(0, 1);
11454         GL_DepthTest(!r_showdisabledepthtest.integer);
11455         GL_DepthMask(false);
11456         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11457
11458         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11459         {
11460                 int triangleindex;
11461                 int bihleafindex;
11462                 qboolean cullbox = false;
11463                 const q3mbrush_t *brush;
11464                 const bih_t *bih = &model->collision_bih;
11465                 const bih_leaf_t *bihleaf;
11466                 float vertex3f[3][3];
11467                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11468                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11469                 {
11470                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11471                                 continue;
11472                         switch (bihleaf->type)
11473                         {
11474                         case BIH_BRUSH:
11475                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11476                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11477                                 {
11478                                         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);
11479                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11480                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11481                                 }
11482                                 break;
11483                         case BIH_COLLISIONTRIANGLE:
11484                                 triangleindex = bihleaf->itemindex;
11485                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11486                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11487                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11488                                 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);
11489                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11490                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11491                                 break;
11492                         case BIH_RENDERTRIANGLE:
11493                                 triangleindex = bihleaf->itemindex;
11494                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11495                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11496                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11497                                 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);
11498                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11499                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11500                                 break;
11501                         }
11502                 }
11503         }
11504
11505         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11506
11507 #ifndef USE_GLES2
11508         if (r_showtris.integer && qglPolygonMode)
11509         {
11510                 if (r_showdisabledepthtest.integer)
11511                 {
11512                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11513                         GL_DepthMask(false);
11514                 }
11515                 else
11516                 {
11517                         GL_BlendFunc(GL_ONE, GL_ZERO);
11518                         GL_DepthMask(true);
11519                 }
11520                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11521                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11522                 {
11523                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11524                                 continue;
11525                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11526                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11527                         {
11528                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11529                                 if (!rsurface.texture->currentlayers->depthmask)
11530                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11531                                 else if (ent == r_refdef.scene.worldentity)
11532                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11533                                 else
11534                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11535                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11536                                 RSurf_DrawBatch();
11537                         }
11538                 }
11539                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11540                 rsurface.texture = NULL;
11541         }
11542
11543         if (r_shownormals.value != 0 && qglBegin)
11544         {
11545                 if (r_showdisabledepthtest.integer)
11546                 {
11547                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11548                         GL_DepthMask(false);
11549                 }
11550                 else
11551                 {
11552                         GL_BlendFunc(GL_ONE, GL_ZERO);
11553                         GL_DepthMask(true);
11554                 }
11555                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11556                 {
11557                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11558                                 continue;
11559                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11560                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11561                         {
11562                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11563                                 qglBegin(GL_LINES);
11564                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11565                                 {
11566                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11567                                         {
11568                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11569                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11570                                                 qglVertex3f(v[0], v[1], v[2]);
11571                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11572                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11573                                                 qglVertex3f(v[0], v[1], v[2]);
11574                                         }
11575                                 }
11576                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11577                                 {
11578                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11579                                         {
11580                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11581                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11582                                                 qglVertex3f(v[0], v[1], v[2]);
11583                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11584                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11585                                                 qglVertex3f(v[0], v[1], v[2]);
11586                                         }
11587                                 }
11588                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11589                                 {
11590                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11591                                         {
11592                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11593                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11594                                                 qglVertex3f(v[0], v[1], v[2]);
11595                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11596                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11597                                                 qglVertex3f(v[0], v[1], v[2]);
11598                                         }
11599                                 }
11600                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11601                                 {
11602                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11603                                         {
11604                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11605                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11606                                                 qglVertex3f(v[0], v[1], v[2]);
11607                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11608                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11609                                                 qglVertex3f(v[0], v[1], v[2]);
11610                                         }
11611                                 }
11612                                 qglEnd();
11613                                 CHECKGLERROR
11614                         }
11615                 }
11616                 rsurface.texture = NULL;
11617         }
11618 #endif
11619 }
11620
11621 int r_maxsurfacelist = 0;
11622 const msurface_t **r_surfacelist = NULL;
11623 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11624 {
11625         int i, j, endj, flagsmask;
11626         dp_model_t *model = r_refdef.scene.worldmodel;
11627         msurface_t *surfaces;
11628         unsigned char *update;
11629         int numsurfacelist = 0;
11630         if (model == NULL)
11631                 return;
11632
11633         if (r_maxsurfacelist < model->num_surfaces)
11634         {
11635                 r_maxsurfacelist = model->num_surfaces;
11636                 if (r_surfacelist)
11637                         Mem_Free((msurface_t**)r_surfacelist);
11638                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11639         }
11640
11641         RSurf_ActiveWorldEntity();
11642
11643         surfaces = model->data_surfaces;
11644         update = model->brushq1.lightmapupdateflags;
11645
11646         // update light styles on this submodel
11647         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11648         {
11649                 model_brush_lightstyleinfo_t *style;
11650                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11651                 {
11652                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11653                         {
11654                                 int *list = style->surfacelist;
11655                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11656                                 for (j = 0;j < style->numsurfaces;j++)
11657                                         update[list[j]] = true;
11658                         }
11659                 }
11660         }
11661
11662         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11663
11664         if (debug)
11665         {
11666                 R_DrawDebugModel();
11667                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11668                 return;
11669         }
11670
11671         rsurface.lightmaptexture = NULL;
11672         rsurface.deluxemaptexture = NULL;
11673         rsurface.uselightmaptexture = false;
11674         rsurface.texture = NULL;
11675         rsurface.rtlight = NULL;
11676         numsurfacelist = 0;
11677         // add visible surfaces to draw list
11678         for (i = 0;i < model->nummodelsurfaces;i++)
11679         {
11680                 j = model->sortedmodelsurfaces[i];
11681                 if (r_refdef.viewcache.world_surfacevisible[j])
11682                         r_surfacelist[numsurfacelist++] = surfaces + j;
11683         }
11684         // update lightmaps if needed
11685         if (model->brushq1.firstrender)
11686         {
11687                 model->brushq1.firstrender = false;
11688                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11689                         if (update[j])
11690                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11691         }
11692         else if (update)
11693         {
11694                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11695                         if (r_refdef.viewcache.world_surfacevisible[j])
11696                                 if (update[j])
11697                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11698         }
11699         // don't do anything if there were no surfaces
11700         if (!numsurfacelist)
11701         {
11702                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11703                 return;
11704         }
11705         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11706
11707         // add to stats if desired
11708         if (r_speeds.integer && !skysurfaces && !depthonly)
11709         {
11710                 r_refdef.stats.world_surfaces += numsurfacelist;
11711                 for (j = 0;j < numsurfacelist;j++)
11712                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11713         }
11714
11715         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11716 }
11717
11718 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11719 {
11720         int i, j, endj, flagsmask;
11721         dp_model_t *model = ent->model;
11722         msurface_t *surfaces;
11723         unsigned char *update;
11724         int numsurfacelist = 0;
11725         if (model == NULL)
11726                 return;
11727
11728         if (r_maxsurfacelist < model->num_surfaces)
11729         {
11730                 r_maxsurfacelist = model->num_surfaces;
11731                 if (r_surfacelist)
11732                         Mem_Free((msurface_t **)r_surfacelist);
11733                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11734         }
11735
11736         // if the model is static it doesn't matter what value we give for
11737         // wantnormals and wanttangents, so this logic uses only rules applicable
11738         // to a model, knowing that they are meaningless otherwise
11739         if (ent == r_refdef.scene.worldentity)
11740                 RSurf_ActiveWorldEntity();
11741         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11742                 RSurf_ActiveModelEntity(ent, false, false, false);
11743         else if (prepass)
11744                 RSurf_ActiveModelEntity(ent, true, true, true);
11745         else if (depthonly)
11746         {
11747                 switch (vid.renderpath)
11748                 {
11749                 case RENDERPATH_GL20:
11750                 case RENDERPATH_D3D9:
11751                 case RENDERPATH_D3D10:
11752                 case RENDERPATH_D3D11:
11753                 case RENDERPATH_SOFT:
11754                 case RENDERPATH_GLES2:
11755                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11756                         break;
11757                 case RENDERPATH_GL11:
11758                 case RENDERPATH_GL13:
11759                 case RENDERPATH_GLES1:
11760                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11761                         break;
11762                 }
11763         }
11764         else
11765         {
11766                 switch (vid.renderpath)
11767                 {
11768                 case RENDERPATH_GL20:
11769                 case RENDERPATH_D3D9:
11770                 case RENDERPATH_D3D10:
11771                 case RENDERPATH_D3D11:
11772                 case RENDERPATH_SOFT:
11773                 case RENDERPATH_GLES2:
11774                         RSurf_ActiveModelEntity(ent, true, true, false);
11775                         break;
11776                 case RENDERPATH_GL11:
11777                 case RENDERPATH_GL13:
11778                 case RENDERPATH_GLES1:
11779                         RSurf_ActiveModelEntity(ent, true, false, false);
11780                         break;
11781                 }
11782         }
11783
11784         surfaces = model->data_surfaces;
11785         update = model->brushq1.lightmapupdateflags;
11786
11787         // update light styles
11788         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11789         {
11790                 model_brush_lightstyleinfo_t *style;
11791                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11792                 {
11793                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11794                         {
11795                                 int *list = style->surfacelist;
11796                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11797                                 for (j = 0;j < style->numsurfaces;j++)
11798                                         update[list[j]] = true;
11799                         }
11800                 }
11801         }
11802
11803         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11804
11805         if (debug)
11806         {
11807                 R_DrawDebugModel();
11808                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11809                 return;
11810         }
11811
11812         rsurface.lightmaptexture = NULL;
11813         rsurface.deluxemaptexture = NULL;
11814         rsurface.uselightmaptexture = false;
11815         rsurface.texture = NULL;
11816         rsurface.rtlight = NULL;
11817         numsurfacelist = 0;
11818         // add visible surfaces to draw list
11819         for (i = 0;i < model->nummodelsurfaces;i++)
11820                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11821         // don't do anything if there were no surfaces
11822         if (!numsurfacelist)
11823         {
11824                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11825                 return;
11826         }
11827         // update lightmaps if needed
11828         if (update)
11829         {
11830                 int updated = 0;
11831                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11832                 {
11833                         if (update[j])
11834                         {
11835                                 updated++;
11836                                 R_BuildLightMap(ent, surfaces + j);
11837                         }
11838                 }
11839         }
11840
11841         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11842
11843         // add to stats if desired
11844         if (r_speeds.integer && !skysurfaces && !depthonly)
11845         {
11846                 r_refdef.stats.entities_surfaces += numsurfacelist;
11847                 for (j = 0;j < numsurfacelist;j++)
11848                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11849         }
11850
11851         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11852 }
11853
11854 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11855 {
11856         static texture_t texture;
11857         static msurface_t surface;
11858         const msurface_t *surfacelist = &surface;
11859
11860         // fake enough texture and surface state to render this geometry
11861
11862         texture.update_lastrenderframe = -1; // regenerate this texture
11863         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11864         texture.currentskinframe = skinframe;
11865         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11866         texture.offsetmapping = OFFSETMAPPING_OFF;
11867         texture.offsetscale = 1;
11868         texture.specularscalemod = 1;
11869         texture.specularpowermod = 1;
11870
11871         surface.texture = &texture;
11872         surface.num_triangles = numtriangles;
11873         surface.num_firsttriangle = firsttriangle;
11874         surface.num_vertices = numvertices;
11875         surface.num_firstvertex = firstvertex;
11876
11877         // now render it
11878         rsurface.texture = R_GetCurrentTexture(surface.texture);
11879         rsurface.lightmaptexture = NULL;
11880         rsurface.deluxemaptexture = NULL;
11881         rsurface.uselightmaptexture = false;
11882         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11883 }
11884
11885 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)
11886 {
11887         static msurface_t surface;
11888         const msurface_t *surfacelist = &surface;
11889
11890         // fake enough texture and surface state to render this geometry
11891         surface.texture = texture;
11892         surface.num_triangles = numtriangles;
11893         surface.num_firsttriangle = firsttriangle;
11894         surface.num_vertices = numvertices;
11895         surface.num_firstvertex = firstvertex;
11896
11897         // now render it
11898         rsurface.texture = R_GetCurrentTexture(surface.texture);
11899         rsurface.lightmaptexture = NULL;
11900         rsurface.deluxemaptexture = NULL;
11901         rsurface.uselightmaptexture = false;
11902         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11903 }