]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
9aeff996875f11d6dc5eb4295a83fc04682b30fc
[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), a value of 2 keeps normalmap shading"};
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                 if (gl_lightmaps.integer < 2)
7978                         t->nmaptexture = r_texture_blanknormalmap;
7979                 t->glosstexture = r_texture_black;
7980                 t->glowtexture = NULL;
7981                 t->fogtexture = NULL;
7982                 t->reflectmasktexture = NULL;
7983                 t->backgroundbasetexture = NULL;
7984                 if (gl_lightmaps.integer < 2)
7985                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7986                 t->backgroundglosstexture = r_texture_black;
7987                 t->backgroundglowtexture = NULL;
7988                 t->specularscale = 0;
7989                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7990         }
7991
7992         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7993         VectorClear(t->dlightcolor);
7994         t->currentnumlayers = 0;
7995         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7996         {
7997                 int blendfunc1, blendfunc2;
7998                 qboolean depthmask;
7999                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8000                 {
8001                         blendfunc1 = GL_SRC_ALPHA;
8002                         blendfunc2 = GL_ONE;
8003                 }
8004                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8005                 {
8006                         blendfunc1 = GL_SRC_ALPHA;
8007                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8008                 }
8009                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8010                 {
8011                         blendfunc1 = t->customblendfunc[0];
8012                         blendfunc2 = t->customblendfunc[1];
8013                 }
8014                 else
8015                 {
8016                         blendfunc1 = GL_ONE;
8017                         blendfunc2 = GL_ZERO;
8018                 }
8019                 // don't colormod evilblend textures
8020                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8021                         VectorSet(t->lightmapcolor, 1, 1, 1);
8022                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8023                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8024                 {
8025                         // fullbright is not affected by r_refdef.lightmapintensity
8026                         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]);
8027                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8028                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8029                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8030                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8031                 }
8032                 else
8033                 {
8034                         vec3_t ambientcolor;
8035                         float colorscale;
8036                         // set the color tint used for lights affecting this surface
8037                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8038                         colorscale = 2;
8039                         // q3bsp has no lightmap updates, so the lightstylevalue that
8040                         // would normally be baked into the lightmap must be
8041                         // applied to the color
8042                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8043                         if (model->type == mod_brushq3)
8044                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8045                         colorscale *= r_refdef.lightmapintensity;
8046                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8047                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8048                         // basic lit geometry
8049                         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]);
8050                         // add pants/shirt if needed
8051                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8052                                 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]);
8053                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8054                                 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]);
8055                         // now add ambient passes if needed
8056                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8057                         {
8058                                 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]);
8059                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8060                                         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]);
8061                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8062                                         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]);
8063                         }
8064                 }
8065                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8066                         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]);
8067                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8068                 {
8069                         // if this is opaque use alpha blend which will darken the earlier
8070                         // passes cheaply.
8071                         //
8072                         // if this is an alpha blended material, all the earlier passes
8073                         // were darkened by fog already, so we only need to add the fog
8074                         // color ontop through the fog mask texture
8075                         //
8076                         // if this is an additive blended material, all the earlier passes
8077                         // were darkened by fog already, and we should not add fog color
8078                         // (because the background was not darkened, there is no fog color
8079                         // that was lost behind it).
8080                         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]);
8081                 }
8082         }
8083
8084         return t->currentframe;
8085 }
8086
8087 rsurfacestate_t rsurface;
8088
8089 void RSurf_ActiveWorldEntity(void)
8090 {
8091         dp_model_t *model = r_refdef.scene.worldmodel;
8092         //if (rsurface.entity == r_refdef.scene.worldentity)
8093         //      return;
8094         rsurface.entity = r_refdef.scene.worldentity;
8095         rsurface.skeleton = NULL;
8096         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8097         rsurface.ent_skinnum = 0;
8098         rsurface.ent_qwskin = -1;
8099         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8100         rsurface.shadertime = r_refdef.scene.time;
8101         rsurface.matrix = identitymatrix;
8102         rsurface.inversematrix = identitymatrix;
8103         rsurface.matrixscale = 1;
8104         rsurface.inversematrixscale = 1;
8105         R_EntityMatrix(&identitymatrix);
8106         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8107         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8108         rsurface.fograngerecip = r_refdef.fograngerecip;
8109         rsurface.fogheightfade = r_refdef.fogheightfade;
8110         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8111         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8112         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8113         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8114         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8115         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8116         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8117         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8118         rsurface.colormod[3] = 1;
8119         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);
8120         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8121         rsurface.frameblend[0].lerp = 1;
8122         rsurface.ent_alttextures = false;
8123         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8124         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8125         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8126         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8127         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8128         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8129         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8130         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8131         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8132         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8133         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8134         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8135         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8136         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8137         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8138         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8139         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8140         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8141         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8142         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8143         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8144         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8145         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8146         rsurface.modelelement3i = model->surfmesh.data_element3i;
8147         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8148         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8149         rsurface.modelelement3s = model->surfmesh.data_element3s;
8150         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8151         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8152         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8153         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8154         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8155         rsurface.modelsurfaces = model->data_surfaces;
8156         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8157         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8158         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8159         rsurface.modelgeneratedvertex = false;
8160         rsurface.batchgeneratedvertex = false;
8161         rsurface.batchfirstvertex = 0;
8162         rsurface.batchnumvertices = 0;
8163         rsurface.batchfirsttriangle = 0;
8164         rsurface.batchnumtriangles = 0;
8165         rsurface.batchvertex3f  = NULL;
8166         rsurface.batchvertex3f_vertexbuffer = NULL;
8167         rsurface.batchvertex3f_bufferoffset = 0;
8168         rsurface.batchsvector3f = NULL;
8169         rsurface.batchsvector3f_vertexbuffer = NULL;
8170         rsurface.batchsvector3f_bufferoffset = 0;
8171         rsurface.batchtvector3f = NULL;
8172         rsurface.batchtvector3f_vertexbuffer = NULL;
8173         rsurface.batchtvector3f_bufferoffset = 0;
8174         rsurface.batchnormal3f  = NULL;
8175         rsurface.batchnormal3f_vertexbuffer = NULL;
8176         rsurface.batchnormal3f_bufferoffset = 0;
8177         rsurface.batchlightmapcolor4f = NULL;
8178         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8179         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8180         rsurface.batchtexcoordtexture2f = NULL;
8181         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8182         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8183         rsurface.batchtexcoordlightmap2f = NULL;
8184         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8185         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8186         rsurface.batchvertexmesh = NULL;
8187         rsurface.batchvertexmeshbuffer = NULL;
8188         rsurface.batchvertex3fbuffer = NULL;
8189         rsurface.batchelement3i = NULL;
8190         rsurface.batchelement3i_indexbuffer = NULL;
8191         rsurface.batchelement3i_bufferoffset = 0;
8192         rsurface.batchelement3s = NULL;
8193         rsurface.batchelement3s_indexbuffer = NULL;
8194         rsurface.batchelement3s_bufferoffset = 0;
8195         rsurface.passcolor4f = NULL;
8196         rsurface.passcolor4f_vertexbuffer = NULL;
8197         rsurface.passcolor4f_bufferoffset = 0;
8198         rsurface.forcecurrenttextureupdate = false;
8199 }
8200
8201 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8202 {
8203         dp_model_t *model = ent->model;
8204         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8205         //      return;
8206         rsurface.entity = (entity_render_t *)ent;
8207         rsurface.skeleton = ent->skeleton;
8208         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8209         rsurface.ent_skinnum = ent->skinnum;
8210         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;
8211         rsurface.ent_flags = ent->flags;
8212         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8213         rsurface.matrix = ent->matrix;
8214         rsurface.inversematrix = ent->inversematrix;
8215         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8216         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8217         R_EntityMatrix(&rsurface.matrix);
8218         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8219         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8220         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8221         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8222         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8223         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8224         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8225         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8226         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8227         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8228         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8229         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8230         rsurface.colormod[3] = ent->alpha;
8231         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8232         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8233         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8234         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8235         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8236         if (ent->model->brush.submodel && !prepass)
8237         {
8238                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8239                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8240         }
8241         if (model->surfmesh.isanimated && model->AnimateVertices)
8242         {
8243                 if (ent->animcache_vertex3f)
8244                 {
8245                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8246                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8247                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8248                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8249                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8250                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8251                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8252                 }
8253                 else if (wanttangents)
8254                 {
8255                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8256                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8257                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8258                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8259                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8260                         rsurface.modelvertexmesh = NULL;
8261                         rsurface.modelvertexmeshbuffer = NULL;
8262                         rsurface.modelvertex3fbuffer = NULL;
8263                 }
8264                 else if (wantnormals)
8265                 {
8266                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8267                         rsurface.modelsvector3f = NULL;
8268                         rsurface.modeltvector3f = NULL;
8269                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8270                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8271                         rsurface.modelvertexmesh = NULL;
8272                         rsurface.modelvertexmeshbuffer = NULL;
8273                         rsurface.modelvertex3fbuffer = NULL;
8274                 }
8275                 else
8276                 {
8277                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8278                         rsurface.modelsvector3f = NULL;
8279                         rsurface.modeltvector3f = NULL;
8280                         rsurface.modelnormal3f = NULL;
8281                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8282                         rsurface.modelvertexmesh = NULL;
8283                         rsurface.modelvertexmeshbuffer = NULL;
8284                         rsurface.modelvertex3fbuffer = NULL;
8285                 }
8286                 rsurface.modelvertex3f_vertexbuffer = 0;
8287                 rsurface.modelvertex3f_bufferoffset = 0;
8288                 rsurface.modelsvector3f_vertexbuffer = 0;
8289                 rsurface.modelsvector3f_bufferoffset = 0;
8290                 rsurface.modeltvector3f_vertexbuffer = 0;
8291                 rsurface.modeltvector3f_bufferoffset = 0;
8292                 rsurface.modelnormal3f_vertexbuffer = 0;
8293                 rsurface.modelnormal3f_bufferoffset = 0;
8294                 rsurface.modelgeneratedvertex = true;
8295         }
8296         else
8297         {
8298                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8299                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8300                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8301                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8302                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8303                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8304                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8305                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8306                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8307                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8308                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8309                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8310                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8311                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8312                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8313                 rsurface.modelgeneratedvertex = false;
8314         }
8315         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8316         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8317         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8318         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8319         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8320         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8321         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8322         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8323         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8324         rsurface.modelelement3i = model->surfmesh.data_element3i;
8325         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8326         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8327         rsurface.modelelement3s = model->surfmesh.data_element3s;
8328         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8329         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8330         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8331         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8332         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8333         rsurface.modelsurfaces = model->data_surfaces;
8334         rsurface.batchgeneratedvertex = false;
8335         rsurface.batchfirstvertex = 0;
8336         rsurface.batchnumvertices = 0;
8337         rsurface.batchfirsttriangle = 0;
8338         rsurface.batchnumtriangles = 0;
8339         rsurface.batchvertex3f  = NULL;
8340         rsurface.batchvertex3f_vertexbuffer = NULL;
8341         rsurface.batchvertex3f_bufferoffset = 0;
8342         rsurface.batchsvector3f = NULL;
8343         rsurface.batchsvector3f_vertexbuffer = NULL;
8344         rsurface.batchsvector3f_bufferoffset = 0;
8345         rsurface.batchtvector3f = NULL;
8346         rsurface.batchtvector3f_vertexbuffer = NULL;
8347         rsurface.batchtvector3f_bufferoffset = 0;
8348         rsurface.batchnormal3f  = NULL;
8349         rsurface.batchnormal3f_vertexbuffer = NULL;
8350         rsurface.batchnormal3f_bufferoffset = 0;
8351         rsurface.batchlightmapcolor4f = NULL;
8352         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8353         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8354         rsurface.batchtexcoordtexture2f = NULL;
8355         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8356         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8357         rsurface.batchtexcoordlightmap2f = NULL;
8358         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8359         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8360         rsurface.batchvertexmesh = NULL;
8361         rsurface.batchvertexmeshbuffer = NULL;
8362         rsurface.batchvertex3fbuffer = NULL;
8363         rsurface.batchelement3i = NULL;
8364         rsurface.batchelement3i_indexbuffer = NULL;
8365         rsurface.batchelement3i_bufferoffset = 0;
8366         rsurface.batchelement3s = NULL;
8367         rsurface.batchelement3s_indexbuffer = NULL;
8368         rsurface.batchelement3s_bufferoffset = 0;
8369         rsurface.passcolor4f = NULL;
8370         rsurface.passcolor4f_vertexbuffer = NULL;
8371         rsurface.passcolor4f_bufferoffset = 0;
8372         rsurface.forcecurrenttextureupdate = false;
8373 }
8374
8375 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)
8376 {
8377         rsurface.entity = r_refdef.scene.worldentity;
8378         rsurface.skeleton = NULL;
8379         rsurface.ent_skinnum = 0;
8380         rsurface.ent_qwskin = -1;
8381         rsurface.ent_flags = entflags;
8382         rsurface.shadertime = r_refdef.scene.time - shadertime;
8383         rsurface.modelnumvertices = numvertices;
8384         rsurface.modelnumtriangles = numtriangles;
8385         rsurface.matrix = *matrix;
8386         rsurface.inversematrix = *inversematrix;
8387         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8388         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8389         R_EntityMatrix(&rsurface.matrix);
8390         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8391         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8392         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8393         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8394         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8395         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8396         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8397         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8398         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8399         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8400         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8401         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8402         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);
8403         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8404         rsurface.frameblend[0].lerp = 1;
8405         rsurface.ent_alttextures = false;
8406         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8407         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8408         if (wanttangents)
8409         {
8410                 rsurface.modelvertex3f = (float *)vertex3f;
8411                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8412                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8413                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8414         }
8415         else if (wantnormals)
8416         {
8417                 rsurface.modelvertex3f = (float *)vertex3f;
8418                 rsurface.modelsvector3f = NULL;
8419                 rsurface.modeltvector3f = NULL;
8420                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8421         }
8422         else
8423         {
8424                 rsurface.modelvertex3f = (float *)vertex3f;
8425                 rsurface.modelsvector3f = NULL;
8426                 rsurface.modeltvector3f = NULL;
8427                 rsurface.modelnormal3f = NULL;
8428         }
8429         rsurface.modelvertexmesh = NULL;
8430         rsurface.modelvertexmeshbuffer = NULL;
8431         rsurface.modelvertex3fbuffer = NULL;
8432         rsurface.modelvertex3f_vertexbuffer = 0;
8433         rsurface.modelvertex3f_bufferoffset = 0;
8434         rsurface.modelsvector3f_vertexbuffer = 0;
8435         rsurface.modelsvector3f_bufferoffset = 0;
8436         rsurface.modeltvector3f_vertexbuffer = 0;
8437         rsurface.modeltvector3f_bufferoffset = 0;
8438         rsurface.modelnormal3f_vertexbuffer = 0;
8439         rsurface.modelnormal3f_bufferoffset = 0;
8440         rsurface.modelgeneratedvertex = true;
8441         rsurface.modellightmapcolor4f  = (float *)color4f;
8442         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8443         rsurface.modellightmapcolor4f_bufferoffset = 0;
8444         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8445         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8446         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8447         rsurface.modeltexcoordlightmap2f  = NULL;
8448         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8449         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8450         rsurface.modelelement3i = (int *)element3i;
8451         rsurface.modelelement3i_indexbuffer = NULL;
8452         rsurface.modelelement3i_bufferoffset = 0;
8453         rsurface.modelelement3s = (unsigned short *)element3s;
8454         rsurface.modelelement3s_indexbuffer = NULL;
8455         rsurface.modelelement3s_bufferoffset = 0;
8456         rsurface.modellightmapoffsets = NULL;
8457         rsurface.modelsurfaces = NULL;
8458         rsurface.batchgeneratedvertex = false;
8459         rsurface.batchfirstvertex = 0;
8460         rsurface.batchnumvertices = 0;
8461         rsurface.batchfirsttriangle = 0;
8462         rsurface.batchnumtriangles = 0;
8463         rsurface.batchvertex3f  = NULL;
8464         rsurface.batchvertex3f_vertexbuffer = NULL;
8465         rsurface.batchvertex3f_bufferoffset = 0;
8466         rsurface.batchsvector3f = NULL;
8467         rsurface.batchsvector3f_vertexbuffer = NULL;
8468         rsurface.batchsvector3f_bufferoffset = 0;
8469         rsurface.batchtvector3f = NULL;
8470         rsurface.batchtvector3f_vertexbuffer = NULL;
8471         rsurface.batchtvector3f_bufferoffset = 0;
8472         rsurface.batchnormal3f  = NULL;
8473         rsurface.batchnormal3f_vertexbuffer = NULL;
8474         rsurface.batchnormal3f_bufferoffset = 0;
8475         rsurface.batchlightmapcolor4f = NULL;
8476         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8477         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8478         rsurface.batchtexcoordtexture2f = NULL;
8479         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8480         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8481         rsurface.batchtexcoordlightmap2f = NULL;
8482         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8483         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8484         rsurface.batchvertexmesh = NULL;
8485         rsurface.batchvertexmeshbuffer = NULL;
8486         rsurface.batchvertex3fbuffer = NULL;
8487         rsurface.batchelement3i = NULL;
8488         rsurface.batchelement3i_indexbuffer = NULL;
8489         rsurface.batchelement3i_bufferoffset = 0;
8490         rsurface.batchelement3s = NULL;
8491         rsurface.batchelement3s_indexbuffer = NULL;
8492         rsurface.batchelement3s_bufferoffset = 0;
8493         rsurface.passcolor4f = NULL;
8494         rsurface.passcolor4f_vertexbuffer = NULL;
8495         rsurface.passcolor4f_bufferoffset = 0;
8496         rsurface.forcecurrenttextureupdate = true;
8497
8498         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8499         {
8500                 if ((wantnormals || wanttangents) && !normal3f)
8501                 {
8502                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8503                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8504                 }
8505                 if (wanttangents && !svector3f)
8506                 {
8507                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8508                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8509                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8510                 }
8511         }
8512 }
8513
8514 float RSurf_FogPoint(const float *v)
8515 {
8516         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8517         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8518         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8519         float FogHeightFade = r_refdef.fogheightfade;
8520         float fogfrac;
8521         unsigned int fogmasktableindex;
8522         if (r_refdef.fogplaneviewabove)
8523                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8524         else
8525                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8526         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8527         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8528 }
8529
8530 float RSurf_FogVertex(const float *v)
8531 {
8532         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8533         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8534         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8535         float FogHeightFade = rsurface.fogheightfade;
8536         float fogfrac;
8537         unsigned int fogmasktableindex;
8538         if (r_refdef.fogplaneviewabove)
8539                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8540         else
8541                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8542         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8543         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8544 }
8545
8546 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8547 {
8548         int i;
8549         for (i = 0;i < numelements;i++)
8550                 outelement3i[i] = inelement3i[i] + adjust;
8551 }
8552
8553 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8554 extern cvar_t gl_vbo;
8555 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8556 {
8557         int deformindex;
8558         int firsttriangle;
8559         int numtriangles;
8560         int firstvertex;
8561         int endvertex;
8562         int numvertices;
8563         int surfacefirsttriangle;
8564         int surfacenumtriangles;
8565         int surfacefirstvertex;
8566         int surfaceendvertex;
8567         int surfacenumvertices;
8568         int batchnumvertices;
8569         int batchnumtriangles;
8570         int needsupdate;
8571         int i, j;
8572         qboolean gaps;
8573         qboolean dynamicvertex;
8574         float amplitude;
8575         float animpos;
8576         float scale;
8577         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8578         float waveparms[4];
8579         q3shaderinfo_deform_t *deform;
8580         const msurface_t *surface, *firstsurface;
8581         r_vertexmesh_t *vertexmesh;
8582         if (!texturenumsurfaces)
8583                 return;
8584         // find vertex range of this surface batch
8585         gaps = false;
8586         firstsurface = texturesurfacelist[0];
8587         firsttriangle = firstsurface->num_firsttriangle;
8588         batchnumvertices = 0;
8589         batchnumtriangles = 0;
8590         firstvertex = endvertex = firstsurface->num_firstvertex;
8591         for (i = 0;i < texturenumsurfaces;i++)
8592         {
8593                 surface = texturesurfacelist[i];
8594                 if (surface != firstsurface + i)
8595                         gaps = true;
8596                 surfacefirstvertex = surface->num_firstvertex;
8597                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8598                 surfacenumvertices = surface->num_vertices;
8599                 surfacenumtriangles = surface->num_triangles;
8600                 if (firstvertex > surfacefirstvertex)
8601                         firstvertex = surfacefirstvertex;
8602                 if (endvertex < surfaceendvertex)
8603                         endvertex = surfaceendvertex;
8604                 batchnumvertices += surfacenumvertices;
8605                 batchnumtriangles += surfacenumtriangles;
8606         }
8607
8608         // we now know the vertex range used, and if there are any gaps in it
8609         rsurface.batchfirstvertex = firstvertex;
8610         rsurface.batchnumvertices = endvertex - firstvertex;
8611         rsurface.batchfirsttriangle = firsttriangle;
8612         rsurface.batchnumtriangles = batchnumtriangles;
8613
8614         // this variable holds flags for which properties have been updated that
8615         // may require regenerating vertexmesh array...
8616         needsupdate = 0;
8617
8618         // check if any dynamic vertex processing must occur
8619         dynamicvertex = false;
8620
8621         // if there is a chance of animated vertex colors, it's a dynamic batch
8622         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8623         {
8624                 dynamicvertex = true;
8625                 batchneed |= BATCHNEED_NOGAPS;
8626                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8627         }
8628
8629         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8630         {
8631                 switch (deform->deform)
8632                 {
8633                 default:
8634                 case Q3DEFORM_PROJECTIONSHADOW:
8635                 case Q3DEFORM_TEXT0:
8636                 case Q3DEFORM_TEXT1:
8637                 case Q3DEFORM_TEXT2:
8638                 case Q3DEFORM_TEXT3:
8639                 case Q3DEFORM_TEXT4:
8640                 case Q3DEFORM_TEXT5:
8641                 case Q3DEFORM_TEXT6:
8642                 case Q3DEFORM_TEXT7:
8643                 case Q3DEFORM_NONE:
8644                         break;
8645                 case Q3DEFORM_AUTOSPRITE:
8646                         dynamicvertex = true;
8647                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8648                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8649                         break;
8650                 case Q3DEFORM_AUTOSPRITE2:
8651                         dynamicvertex = true;
8652                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8653                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8654                         break;
8655                 case Q3DEFORM_NORMAL:
8656                         dynamicvertex = true;
8657                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8658                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8659                         break;
8660                 case Q3DEFORM_WAVE:
8661                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8662                                 break; // if wavefunc is a nop, ignore this transform
8663                         dynamicvertex = true;
8664                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8665                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8666                         break;
8667                 case Q3DEFORM_BULGE:
8668                         dynamicvertex = true;
8669                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8670                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8671                         break;
8672                 case Q3DEFORM_MOVE:
8673                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8674                                 break; // if wavefunc is a nop, ignore this transform
8675                         dynamicvertex = true;
8676                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8677                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8678                         break;
8679                 }
8680         }
8681         switch(rsurface.texture->tcgen.tcgen)
8682         {
8683         default:
8684         case Q3TCGEN_TEXTURE:
8685                 break;
8686         case Q3TCGEN_LIGHTMAP:
8687                 dynamicvertex = true;
8688                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8689                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8690                 break;
8691         case Q3TCGEN_VECTOR:
8692                 dynamicvertex = true;
8693                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8694                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8695                 break;
8696         case Q3TCGEN_ENVIRONMENT:
8697                 dynamicvertex = true;
8698                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8699                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8700                 break;
8701         }
8702         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8703         {
8704                 dynamicvertex = true;
8705                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8706                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8707         }
8708
8709         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8710         {
8711                 dynamicvertex = true;
8712                 batchneed |= BATCHNEED_NOGAPS;
8713                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8714         }
8715
8716         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8717         {
8718                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8719                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8720                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8721                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8722                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8723                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8724                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8725         }
8726
8727         // when the model data has no vertex buffer (dynamic mesh), we need to
8728         // eliminate gaps
8729         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8730                 batchneed |= BATCHNEED_NOGAPS;
8731
8732         // if needsupdate, we have to do a dynamic vertex batch for sure
8733         if (needsupdate & batchneed)
8734                 dynamicvertex = true;
8735
8736         // see if we need to build vertexmesh from arrays
8737         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8738                 dynamicvertex = true;
8739
8740         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8741         // also some drivers strongly dislike firstvertex
8742         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8743                 dynamicvertex = true;
8744
8745         rsurface.batchvertex3f = rsurface.modelvertex3f;
8746         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8747         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8748         rsurface.batchsvector3f = rsurface.modelsvector3f;
8749         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8750         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8751         rsurface.batchtvector3f = rsurface.modeltvector3f;
8752         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8753         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8754         rsurface.batchnormal3f = rsurface.modelnormal3f;
8755         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8756         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8757         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8758         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8759         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8760         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8761         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8762         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8763         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8764         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8765         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8766         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8767         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8768         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8769         rsurface.batchelement3i = rsurface.modelelement3i;
8770         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8771         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8772         rsurface.batchelement3s = rsurface.modelelement3s;
8773         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8774         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8775
8776         // if any dynamic vertex processing has to occur in software, we copy the
8777         // entire surface list together before processing to rebase the vertices
8778         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8779         //
8780         // if any gaps exist and we do not have a static vertex buffer, we have to
8781         // copy the surface list together to avoid wasting upload bandwidth on the
8782         // vertices in the gaps.
8783         //
8784         // if gaps exist and we have a static vertex buffer, we still have to
8785         // combine the index buffer ranges into one dynamic index buffer.
8786         //
8787         // in all cases we end up with data that can be drawn in one call.
8788
8789         if (!dynamicvertex)
8790         {
8791                 // static vertex data, just set pointers...
8792                 rsurface.batchgeneratedvertex = false;
8793                 // if there are gaps, we want to build a combined index buffer,
8794                 // otherwise use the original static buffer with an appropriate offset
8795                 if (gaps)
8796                 {
8797                         // build a new triangle elements array for this batch
8798                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8799                         rsurface.batchfirsttriangle = 0;
8800                         numtriangles = 0;
8801                         for (i = 0;i < texturenumsurfaces;i++)
8802                         {
8803                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8804                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8805                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8806                                 numtriangles += surfacenumtriangles;
8807                         }
8808                         rsurface.batchelement3i_indexbuffer = NULL;
8809                         rsurface.batchelement3i_bufferoffset = 0;
8810                         rsurface.batchelement3s = NULL;
8811                         rsurface.batchelement3s_indexbuffer = NULL;
8812                         rsurface.batchelement3s_bufferoffset = 0;
8813                         if (endvertex <= 65536)
8814                         {
8815                                 // make a 16bit (unsigned short) index array if possible
8816                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8817                                 for (i = 0;i < numtriangles*3;i++)
8818                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8819                         }
8820                 }
8821                 return;
8822         }
8823
8824         // something needs software processing, do it for real...
8825         // we only directly handle separate array data in this case and then
8826         // generate interleaved data if needed...
8827         rsurface.batchgeneratedvertex = true;
8828
8829         // now copy the vertex data into a combined array and make an index array
8830         // (this is what Quake3 does all the time)
8831         //if (gaps || rsurface.batchfirstvertex)
8832         {
8833                 rsurface.batchvertex3fbuffer = NULL;
8834                 rsurface.batchvertexmesh = NULL;
8835                 rsurface.batchvertexmeshbuffer = NULL;
8836                 rsurface.batchvertex3f = NULL;
8837                 rsurface.batchvertex3f_vertexbuffer = NULL;
8838                 rsurface.batchvertex3f_bufferoffset = 0;
8839                 rsurface.batchsvector3f = NULL;
8840                 rsurface.batchsvector3f_vertexbuffer = NULL;
8841                 rsurface.batchsvector3f_bufferoffset = 0;
8842                 rsurface.batchtvector3f = NULL;
8843                 rsurface.batchtvector3f_vertexbuffer = NULL;
8844                 rsurface.batchtvector3f_bufferoffset = 0;
8845                 rsurface.batchnormal3f = NULL;
8846                 rsurface.batchnormal3f_vertexbuffer = NULL;
8847                 rsurface.batchnormal3f_bufferoffset = 0;
8848                 rsurface.batchlightmapcolor4f = NULL;
8849                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8850                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8851                 rsurface.batchtexcoordtexture2f = NULL;
8852                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8853                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8854                 rsurface.batchtexcoordlightmap2f = NULL;
8855                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8856                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8857                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8858                 rsurface.batchelement3i_indexbuffer = NULL;
8859                 rsurface.batchelement3i_bufferoffset = 0;
8860                 rsurface.batchelement3s = NULL;
8861                 rsurface.batchelement3s_indexbuffer = NULL;
8862                 rsurface.batchelement3s_bufferoffset = 0;
8863                 // we'll only be setting up certain arrays as needed
8864                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8865                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8866                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8867                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8869                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8871                 {
8872                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8873                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8874                 }
8875                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8876                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8877                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8878                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8879                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8880                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8881                 numvertices = 0;
8882                 numtriangles = 0;
8883                 for (i = 0;i < texturenumsurfaces;i++)
8884                 {
8885                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8886                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8887                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8888                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8889                         // copy only the data requested
8890                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8891                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8892                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8893                         {
8894                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8895                                 {
8896                                         if (rsurface.batchvertex3f)
8897                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8898                                         else
8899                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8900                                 }
8901                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8902                                 {
8903                                         if (rsurface.modelnormal3f)
8904                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8905                                         else
8906                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8907                                 }
8908                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8909                                 {
8910                                         if (rsurface.modelsvector3f)
8911                                         {
8912                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8913                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8914                                         }
8915                                         else
8916                                         {
8917                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8918                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8919                                         }
8920                                 }
8921                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8922                                 {
8923                                         if (rsurface.modellightmapcolor4f)
8924                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8925                                         else
8926                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8927                                 }
8928                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8929                                 {
8930                                         if (rsurface.modeltexcoordtexture2f)
8931                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8932                                         else
8933                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8934                                 }
8935                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8936                                 {
8937                                         if (rsurface.modeltexcoordlightmap2f)
8938                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8939                                         else
8940                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8941                                 }
8942                         }
8943                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8944                         numvertices += surfacenumvertices;
8945                         numtriangles += surfacenumtriangles;
8946                 }
8947
8948                 // generate a 16bit index array as well if possible
8949                 // (in general, dynamic batches fit)
8950                 if (numvertices <= 65536)
8951                 {
8952                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8953                         for (i = 0;i < numtriangles*3;i++)
8954                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8955                 }
8956
8957                 // since we've copied everything, the batch now starts at 0
8958                 rsurface.batchfirstvertex = 0;
8959                 rsurface.batchnumvertices = batchnumvertices;
8960                 rsurface.batchfirsttriangle = 0;
8961                 rsurface.batchnumtriangles = batchnumtriangles;
8962         }
8963
8964         // q1bsp surfaces rendered in vertex color mode have to have colors
8965         // calculated based on lightstyles
8966         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8967         {
8968                 // generate color arrays for the surfaces in this list
8969                 int c[4];
8970                 int scale;
8971                 int size3;
8972                 const int *offsets;
8973                 const unsigned char *lm;
8974                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8975                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8976                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8977                 numvertices = 0;
8978                 for (i = 0;i < texturenumsurfaces;i++)
8979                 {
8980                         surface = texturesurfacelist[i];
8981                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8982                         surfacenumvertices = surface->num_vertices;
8983                         if (surface->lightmapinfo->samples)
8984                         {
8985                                 for (j = 0;j < surfacenumvertices;j++)
8986                                 {
8987                                         lm = surface->lightmapinfo->samples + offsets[j];
8988                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8989                                         VectorScale(lm, scale, c);
8990                                         if (surface->lightmapinfo->styles[1] != 255)
8991                                         {
8992                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8993                                                 lm += size3;
8994                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8995                                                 VectorMA(c, scale, lm, c);
8996                                                 if (surface->lightmapinfo->styles[2] != 255)
8997                                                 {
8998                                                         lm += size3;
8999                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9000                                                         VectorMA(c, scale, lm, c);
9001                                                         if (surface->lightmapinfo->styles[3] != 255)
9002                                                         {
9003                                                                 lm += size3;
9004                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9005                                                                 VectorMA(c, scale, lm, c);
9006                                                         }
9007                                                 }
9008                                         }
9009                                         c[0] >>= 7;
9010                                         c[1] >>= 7;
9011                                         c[2] >>= 7;
9012                                         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);
9013                                         numvertices++;
9014                                 }
9015                         }
9016                         else
9017                         {
9018                                 for (j = 0;j < surfacenumvertices;j++)
9019                                 {
9020                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9021                                         numvertices++;
9022                                 }
9023                         }
9024                 }
9025         }
9026
9027         // if vertices are deformed (sprite flares and things in maps, possibly
9028         // water waves, bulges and other deformations), modify the copied vertices
9029         // in place
9030         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9031         {
9032                 switch (deform->deform)
9033                 {
9034                 default:
9035                 case Q3DEFORM_PROJECTIONSHADOW:
9036                 case Q3DEFORM_TEXT0:
9037                 case Q3DEFORM_TEXT1:
9038                 case Q3DEFORM_TEXT2:
9039                 case Q3DEFORM_TEXT3:
9040                 case Q3DEFORM_TEXT4:
9041                 case Q3DEFORM_TEXT5:
9042                 case Q3DEFORM_TEXT6:
9043                 case Q3DEFORM_TEXT7:
9044                 case Q3DEFORM_NONE:
9045                         break;
9046                 case Q3DEFORM_AUTOSPRITE:
9047                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9048                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9049                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9050                         VectorNormalize(newforward);
9051                         VectorNormalize(newright);
9052                         VectorNormalize(newup);
9053 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9054 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9055 //                      rsurface.batchvertex3f_bufferoffset = 0;
9056 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9057 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9058 //                      rsurface.batchsvector3f_bufferoffset = 0;
9059 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9060 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9061 //                      rsurface.batchtvector3f_bufferoffset = 0;
9062 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9063 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9064 //                      rsurface.batchnormal3f_bufferoffset = 0;
9065                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9066                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9067                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9068                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9069                                 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);
9070                         // a single autosprite surface can contain multiple sprites...
9071                         for (j = 0;j < batchnumvertices - 3;j += 4)
9072                         {
9073                                 VectorClear(center);
9074                                 for (i = 0;i < 4;i++)
9075                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9076                                 VectorScale(center, 0.25f, center);
9077                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9078                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9079                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9080                                 for (i = 0;i < 4;i++)
9081                                 {
9082                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9083                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9084                                 }
9085                         }
9086                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9087                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9088                         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);
9089                         break;
9090                 case Q3DEFORM_AUTOSPRITE2:
9091                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9092                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9093                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9094                         VectorNormalize(newforward);
9095                         VectorNormalize(newright);
9096                         VectorNormalize(newup);
9097 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9098 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9099 //                      rsurface.batchvertex3f_bufferoffset = 0;
9100                         {
9101                                 const float *v1, *v2;
9102                                 vec3_t start, end;
9103                                 float f, l;
9104                                 struct
9105                                 {
9106                                         float length2;
9107                                         const float *v1;
9108                                         const float *v2;
9109                                 }
9110                                 shortest[2];
9111                                 memset(shortest, 0, sizeof(shortest));
9112                                 // a single autosprite surface can contain multiple sprites...
9113                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9114                                 {
9115                                         VectorClear(center);
9116                                         for (i = 0;i < 4;i++)
9117                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9118                                         VectorScale(center, 0.25f, center);
9119                                         // find the two shortest edges, then use them to define the
9120                                         // axis vectors for rotating around the central axis
9121                                         for (i = 0;i < 6;i++)
9122                                         {
9123                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9124                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9125                                                 l = VectorDistance2(v1, v2);
9126                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9127                                                 if (v1[2] != v2[2])
9128                                                         l += (1.0f / 1024.0f);
9129                                                 if (shortest[0].length2 > l || i == 0)
9130                                                 {
9131                                                         shortest[1] = shortest[0];
9132                                                         shortest[0].length2 = l;
9133                                                         shortest[0].v1 = v1;
9134                                                         shortest[0].v2 = v2;
9135                                                 }
9136                                                 else if (shortest[1].length2 > l || i == 1)
9137                                                 {
9138                                                         shortest[1].length2 = l;
9139                                                         shortest[1].v1 = v1;
9140                                                         shortest[1].v2 = v2;
9141                                                 }
9142                                         }
9143                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9144                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9145                                         // this calculates the right vector from the shortest edge
9146                                         // and the up vector from the edge midpoints
9147                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9148                                         VectorNormalize(right);
9149                                         VectorSubtract(end, start, up);
9150                                         VectorNormalize(up);
9151                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9152                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9153                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9154                                         VectorNegate(forward, forward);
9155                                         VectorReflect(forward, 0, up, forward);
9156                                         VectorNormalize(forward);
9157                                         CrossProduct(up, forward, newright);
9158                                         VectorNormalize(newright);
9159                                         // rotate the quad around the up axis vector, this is made
9160                                         // especially easy by the fact we know the quad is flat,
9161                                         // so we only have to subtract the center position and
9162                                         // measure distance along the right vector, and then
9163                                         // multiply that by the newright vector and add back the
9164                                         // center position
9165                                         // we also need to subtract the old position to undo the
9166                                         // displacement from the center, which we do with a
9167                                         // DotProduct, the subtraction/addition of center is also
9168                                         // optimized into DotProducts here
9169                                         l = DotProduct(right, center);
9170                                         for (i = 0;i < 4;i++)
9171                                         {
9172                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9173                                                 f = DotProduct(right, v1) - l;
9174                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9175                                         }
9176                                 }
9177                         }
9178                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9179                         {
9180 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9181 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9182 //                              rsurface.batchnormal3f_bufferoffset = 0;
9183                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9184                         }
9185                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9186                         {
9187 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9188 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9189 //                              rsurface.batchsvector3f_bufferoffset = 0;
9190 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9191 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9192 //                              rsurface.batchtvector3f_bufferoffset = 0;
9193                                 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);
9194                         }
9195                         break;
9196                 case Q3DEFORM_NORMAL:
9197                         // deform the normals to make reflections wavey
9198                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9199                         rsurface.batchnormal3f_vertexbuffer = NULL;
9200                         rsurface.batchnormal3f_bufferoffset = 0;
9201                         for (j = 0;j < batchnumvertices;j++)
9202                         {
9203                                 float vertex[3];
9204                                 float *normal = rsurface.batchnormal3f + 3*j;
9205                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9206                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9207                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9208                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9209                                 VectorNormalize(normal);
9210                         }
9211                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9212                         {
9213 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9214 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9215 //                              rsurface.batchsvector3f_bufferoffset = 0;
9216 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9217 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9218 //                              rsurface.batchtvector3f_bufferoffset = 0;
9219                                 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);
9220                         }
9221                         break;
9222                 case Q3DEFORM_WAVE:
9223                         // deform vertex array to make wavey water and flags and such
9224                         waveparms[0] = deform->waveparms[0];
9225                         waveparms[1] = deform->waveparms[1];
9226                         waveparms[2] = deform->waveparms[2];
9227                         waveparms[3] = deform->waveparms[3];
9228                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9229                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9230                         // this is how a divisor of vertex influence on deformation
9231                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9232                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9233 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9234 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9235 //                      rsurface.batchvertex3f_bufferoffset = 0;
9236 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9237 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9238 //                      rsurface.batchnormal3f_bufferoffset = 0;
9239                         for (j = 0;j < batchnumvertices;j++)
9240                         {
9241                                 // if the wavefunc depends on time, evaluate it per-vertex
9242                                 if (waveparms[3])
9243                                 {
9244                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9245                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9246                                 }
9247                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9248                         }
9249                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9250                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9251                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9252                         {
9253 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9254 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9255 //                              rsurface.batchsvector3f_bufferoffset = 0;
9256 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9257 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9258 //                              rsurface.batchtvector3f_bufferoffset = 0;
9259                                 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);
9260                         }
9261                         break;
9262                 case Q3DEFORM_BULGE:
9263                         // deform vertex array to make the surface have moving bulges
9264 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9265 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9266 //                      rsurface.batchvertex3f_bufferoffset = 0;
9267 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9268 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9269 //                      rsurface.batchnormal3f_bufferoffset = 0;
9270                         for (j = 0;j < batchnumvertices;j++)
9271                         {
9272                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9273                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9274                         }
9275                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9276                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9277                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9278                         {
9279 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9280 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9281 //                              rsurface.batchsvector3f_bufferoffset = 0;
9282 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9283 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9284 //                              rsurface.batchtvector3f_bufferoffset = 0;
9285                                 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);
9286                         }
9287                         break;
9288                 case Q3DEFORM_MOVE:
9289                         // deform vertex array
9290                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9291                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9292                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9293                         VectorScale(deform->parms, scale, waveparms);
9294 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9295 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9296 //                      rsurface.batchvertex3f_bufferoffset = 0;
9297                         for (j = 0;j < batchnumvertices;j++)
9298                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9299                         break;
9300                 }
9301         }
9302
9303         // generate texcoords based on the chosen texcoord source
9304         switch(rsurface.texture->tcgen.tcgen)
9305         {
9306         default:
9307         case Q3TCGEN_TEXTURE:
9308                 break;
9309         case Q3TCGEN_LIGHTMAP:
9310 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9311 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9312 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9313                 if (rsurface.batchtexcoordlightmap2f)
9314                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9315                 break;
9316         case Q3TCGEN_VECTOR:
9317 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9318 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9319 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9320                 for (j = 0;j < batchnumvertices;j++)
9321                 {
9322                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9323                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9324                 }
9325                 break;
9326         case Q3TCGEN_ENVIRONMENT:
9327                 // make environment reflections using a spheremap
9328                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9329                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9330                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9331                 for (j = 0;j < batchnumvertices;j++)
9332                 {
9333                         // identical to Q3A's method, but executed in worldspace so
9334                         // carried models can be shiny too
9335
9336                         float viewer[3], d, reflected[3], worldreflected[3];
9337
9338                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9339                         // VectorNormalize(viewer);
9340
9341                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9342
9343                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9344                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9345                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9346                         // note: this is proportinal to viewer, so we can normalize later
9347
9348                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9349                         VectorNormalize(worldreflected);
9350
9351                         // note: this sphere map only uses world x and z!
9352                         // so positive and negative y will LOOK THE SAME.
9353                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9354                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9355                 }
9356                 break;
9357         }
9358         // the only tcmod that needs software vertex processing is turbulent, so
9359         // check for it here and apply the changes if needed
9360         // and we only support that as the first one
9361         // (handling a mixture of turbulent and other tcmods would be problematic
9362         //  without punting it entirely to a software path)
9363         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9364         {
9365                 amplitude = rsurface.texture->tcmods[0].parms[1];
9366                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9367 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9368 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9369 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9370                 for (j = 0;j < batchnumvertices;j++)
9371                 {
9372                         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);
9373                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9374                 }
9375         }
9376
9377         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9378         {
9379                 // convert the modified arrays to vertex structs
9380 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9381 //              rsurface.batchvertexmeshbuffer = NULL;
9382                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9383                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9384                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9385                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9386                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9387                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9388                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9389                 {
9390                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9391                         {
9392                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9393                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9394                         }
9395                 }
9396                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9397                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9398                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9399                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9400                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9401                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9402                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9403                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9404                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9405         }
9406 }
9407
9408 void RSurf_DrawBatch(void)
9409 {
9410         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9411         // through the pipeline, killing it earlier in the pipeline would have
9412         // per-surface overhead rather than per-batch overhead, so it's best to
9413         // reject it here, before it hits glDraw.
9414         if (rsurface.batchnumtriangles == 0)
9415                 return;
9416 #if 0
9417         // batch debugging code
9418         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9419         {
9420                 int i;
9421                 int j;
9422                 int c;
9423                 const int *e;
9424                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9425                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9426                 {
9427                         c = e[i];
9428                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9429                         {
9430                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9431                                 {
9432                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9433                                                 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);
9434                                         break;
9435                                 }
9436                         }
9437                 }
9438         }
9439 #endif
9440         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);
9441 }
9442
9443 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9444 {
9445         // pick the closest matching water plane
9446         int planeindex, vertexindex, bestplaneindex = -1;
9447         float d, bestd;
9448         vec3_t vert;
9449         const float *v;
9450         r_waterstate_waterplane_t *p;
9451         qboolean prepared = false;
9452         bestd = 0;
9453         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9454         {
9455                 if(p->camera_entity != rsurface.texture->camera_entity)
9456                         continue;
9457                 d = 0;
9458                 if(!prepared)
9459                 {
9460                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9461                         prepared = true;
9462                         if(rsurface.batchnumvertices == 0)
9463                                 break;
9464                 }
9465                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9466                 {
9467                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9468                         d += fabs(PlaneDiff(vert, &p->plane));
9469                 }
9470                 if (bestd > d || bestplaneindex < 0)
9471                 {
9472                         bestd = d;
9473                         bestplaneindex = planeindex;
9474                 }
9475         }
9476         return bestplaneindex;
9477         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9478         // this situation though, as it might be better to render single larger
9479         // batches with useless stuff (backface culled for example) than to
9480         // render multiple smaller batches
9481 }
9482
9483 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9484 {
9485         int i;
9486         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9487         rsurface.passcolor4f_vertexbuffer = 0;
9488         rsurface.passcolor4f_bufferoffset = 0;
9489         for (i = 0;i < rsurface.batchnumvertices;i++)
9490                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9491 }
9492
9493 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9494 {
9495         int i;
9496         float f;
9497         const float *v;
9498         const float *c;
9499         float *c2;
9500         if (rsurface.passcolor4f)
9501         {
9502                 // generate color arrays
9503                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9504                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9505                 rsurface.passcolor4f_vertexbuffer = 0;
9506                 rsurface.passcolor4f_bufferoffset = 0;
9507                 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)
9508                 {
9509                         f = RSurf_FogVertex(v);
9510                         c2[0] = c[0] * f;
9511                         c2[1] = c[1] * f;
9512                         c2[2] = c[2] * f;
9513                         c2[3] = c[3];
9514                 }
9515         }
9516         else
9517         {
9518                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9519                 rsurface.passcolor4f_vertexbuffer = 0;
9520                 rsurface.passcolor4f_bufferoffset = 0;
9521                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9522                 {
9523                         f = RSurf_FogVertex(v);
9524                         c2[0] = f;
9525                         c2[1] = f;
9526                         c2[2] = f;
9527                         c2[3] = 1;
9528                 }
9529         }
9530 }
9531
9532 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9533 {
9534         int i;
9535         float f;
9536         const float *v;
9537         const float *c;
9538         float *c2;
9539         if (!rsurface.passcolor4f)
9540                 return;
9541         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9542         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9543         rsurface.passcolor4f_vertexbuffer = 0;
9544         rsurface.passcolor4f_bufferoffset = 0;
9545         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)
9546         {
9547                 f = RSurf_FogVertex(v);
9548                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9549                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9550                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9551                 c2[3] = c[3];
9552         }
9553 }
9554
9555 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9556 {
9557         int i;
9558         const float *c;
9559         float *c2;
9560         if (!rsurface.passcolor4f)
9561                 return;
9562         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9563         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9564         rsurface.passcolor4f_vertexbuffer = 0;
9565         rsurface.passcolor4f_bufferoffset = 0;
9566         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9567         {
9568                 c2[0] = c[0] * r;
9569                 c2[1] = c[1] * g;
9570                 c2[2] = c[2] * b;
9571                 c2[3] = c[3] * a;
9572         }
9573 }
9574
9575 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9576 {
9577         int i;
9578         const float *c;
9579         float *c2;
9580         if (!rsurface.passcolor4f)
9581                 return;
9582         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9583         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9584         rsurface.passcolor4f_vertexbuffer = 0;
9585         rsurface.passcolor4f_bufferoffset = 0;
9586         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9587         {
9588                 c2[0] = c[0] + r_refdef.scene.ambient;
9589                 c2[1] = c[1] + r_refdef.scene.ambient;
9590                 c2[2] = c[2] + r_refdef.scene.ambient;
9591                 c2[3] = c[3];
9592         }
9593 }
9594
9595 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9596 {
9597         // TODO: optimize
9598         rsurface.passcolor4f = NULL;
9599         rsurface.passcolor4f_vertexbuffer = 0;
9600         rsurface.passcolor4f_bufferoffset = 0;
9601         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9602         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9603         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9604         GL_Color(r, g, b, a);
9605         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9606         RSurf_DrawBatch();
9607 }
9608
9609 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9610 {
9611         // TODO: optimize applyfog && applycolor case
9612         // just apply fog if necessary, and tint the fog color array if necessary
9613         rsurface.passcolor4f = NULL;
9614         rsurface.passcolor4f_vertexbuffer = 0;
9615         rsurface.passcolor4f_bufferoffset = 0;
9616         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9617         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9618         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9619         GL_Color(r, g, b, a);
9620         RSurf_DrawBatch();
9621 }
9622
9623 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9624 {
9625         // TODO: optimize
9626         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9627         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9628         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9629         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9630         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9631         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9632         GL_Color(r, g, b, a);
9633         RSurf_DrawBatch();
9634 }
9635
9636 static void RSurf_DrawBatch_GL11_ClampColor(void)
9637 {
9638         int i;
9639         const float *c1;
9640         float *c2;
9641         if (!rsurface.passcolor4f)
9642                 return;
9643         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9644         {
9645                 c2[0] = bound(0.0f, c1[0], 1.0f);
9646                 c2[1] = bound(0.0f, c1[1], 1.0f);
9647                 c2[2] = bound(0.0f, c1[2], 1.0f);
9648                 c2[3] = bound(0.0f, c1[3], 1.0f);
9649         }
9650 }
9651
9652 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9653 {
9654         int i;
9655         float f;
9656         const float *v;
9657         const float *n;
9658         float *c;
9659         //vec3_t eyedir;
9660
9661         // fake shading
9662         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9663         rsurface.passcolor4f_vertexbuffer = 0;
9664         rsurface.passcolor4f_bufferoffset = 0;
9665         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)
9666         {
9667                 f = -DotProduct(r_refdef.view.forward, n);
9668                 f = max(0, f);
9669                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9670                 f *= r_refdef.lightmapintensity;
9671                 Vector4Set(c, f, f, f, 1);
9672         }
9673 }
9674
9675 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9676 {
9677         RSurf_DrawBatch_GL11_ApplyFakeLight();
9678         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9679         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9680         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9681         GL_Color(r, g, b, a);
9682         RSurf_DrawBatch();
9683 }
9684
9685 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9686 {
9687         int i;
9688         float f;
9689         float alpha;
9690         const float *v;
9691         const float *n;
9692         float *c;
9693         vec3_t ambientcolor;
9694         vec3_t diffusecolor;
9695         vec3_t lightdir;
9696         // TODO: optimize
9697         // model lighting
9698         VectorCopy(rsurface.modellight_lightdir, lightdir);
9699         f = 0.5f * r_refdef.lightmapintensity;
9700         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9701         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9702         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9703         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9704         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9705         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9706         alpha = *a;
9707         if (VectorLength2(diffusecolor) > 0)
9708         {
9709                 // q3-style directional shading
9710                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9711                 rsurface.passcolor4f_vertexbuffer = 0;
9712                 rsurface.passcolor4f_bufferoffset = 0;
9713                 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)
9714                 {
9715                         if ((f = DotProduct(n, lightdir)) > 0)
9716                                 VectorMA(ambientcolor, f, diffusecolor, c);
9717                         else
9718                                 VectorCopy(ambientcolor, c);
9719                         c[3] = alpha;
9720                 }
9721                 *r = 1;
9722                 *g = 1;
9723                 *b = 1;
9724                 *a = 1;
9725                 *applycolor = false;
9726         }
9727         else
9728         {
9729                 *r = ambientcolor[0];
9730                 *g = ambientcolor[1];
9731                 *b = ambientcolor[2];
9732                 rsurface.passcolor4f = NULL;
9733                 rsurface.passcolor4f_vertexbuffer = 0;
9734                 rsurface.passcolor4f_bufferoffset = 0;
9735         }
9736 }
9737
9738 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9739 {
9740         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9741         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9742         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9743         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9744         GL_Color(r, g, b, a);
9745         RSurf_DrawBatch();
9746 }
9747
9748 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9749 {
9750         int i;
9751         float f;
9752         const float *v;
9753         float *c;
9754
9755         // fake shading
9756         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9757         rsurface.passcolor4f_vertexbuffer = 0;
9758         rsurface.passcolor4f_bufferoffset = 0;
9759
9760         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9761         {
9762                 f = 1 - RSurf_FogVertex(v);
9763                 c[0] = r;
9764                 c[1] = g;
9765                 c[2] = b;
9766                 c[3] = f * a;
9767         }
9768 }
9769
9770 void RSurf_SetupDepthAndCulling(void)
9771 {
9772         // submodels are biased to avoid z-fighting with world surfaces that they
9773         // may be exactly overlapping (avoids z-fighting artifacts on certain
9774         // doors and things in Quake maps)
9775         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9776         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9777         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9778         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9779 }
9780
9781 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9782 {
9783         // transparent sky would be ridiculous
9784         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9785                 return;
9786         R_SetupShader_Generic_NoTexture(false, false);
9787         skyrenderlater = true;
9788         RSurf_SetupDepthAndCulling();
9789         GL_DepthMask(true);
9790         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9791         // skymasking on them, and Quake3 never did sky masking (unlike
9792         // software Quake and software Quake2), so disable the sky masking
9793         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9794         // and skymasking also looks very bad when noclipping outside the
9795         // level, so don't use it then either.
9796         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9797         {
9798                 R_Mesh_ResetTextureState();
9799                 if (skyrendermasked)
9800                 {
9801                         R_SetupShader_DepthOrShadow(false, false);
9802                         // depth-only (masking)
9803                         GL_ColorMask(0,0,0,0);
9804                         // just to make sure that braindead drivers don't draw
9805                         // anything despite that colormask...
9806                         GL_BlendFunc(GL_ZERO, GL_ONE);
9807                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808                         if (rsurface.batchvertex3fbuffer)
9809                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9810                         else
9811                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9812                 }
9813                 else
9814                 {
9815                         R_SetupShader_Generic_NoTexture(false, false);
9816                         // fog sky
9817                         GL_BlendFunc(GL_ONE, GL_ZERO);
9818                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9819                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9820                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9821                 }
9822                 RSurf_DrawBatch();
9823                 if (skyrendermasked)
9824                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9825         }
9826         R_Mesh_ResetTextureState();
9827         GL_Color(1, 1, 1, 1);
9828 }
9829
9830 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9831 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9832 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9833 {
9834         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9835                 return;
9836         if (prepass)
9837         {
9838                 // render screenspace normalmap to texture
9839                 GL_DepthMask(true);
9840                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9841                 RSurf_DrawBatch();
9842                 return;
9843         }
9844
9845         // bind lightmap texture
9846
9847         // water/refraction/reflection/camera surfaces have to be handled specially
9848         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9849         {
9850                 int start, end, startplaneindex;
9851                 for (start = 0;start < texturenumsurfaces;start = end)
9852                 {
9853                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9854                         if(startplaneindex < 0)
9855                         {
9856                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9857                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9858                                 end = start + 1;
9859                                 continue;
9860                         }
9861                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9862                                 ;
9863                         // now that we have a batch using the same planeindex, render it
9864                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9865                         {
9866                                 // render water or distortion background
9867                                 GL_DepthMask(true);
9868                                 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);
9869                                 RSurf_DrawBatch();
9870                                 // blend surface on top
9871                                 GL_DepthMask(false);
9872                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9873                                 RSurf_DrawBatch();
9874                         }
9875                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9876                         {
9877                                 // render surface with reflection texture as input
9878                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9879                                 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);
9880                                 RSurf_DrawBatch();
9881                         }
9882                 }
9883                 return;
9884         }
9885
9886         // render surface batch normally
9887         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9888         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);
9889         RSurf_DrawBatch();
9890 }
9891
9892 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9893 {
9894         // OpenGL 1.3 path - anything not completely ancient
9895         qboolean applycolor;
9896         qboolean applyfog;
9897         int layerindex;
9898         const texturelayer_t *layer;
9899         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);
9900         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9901
9902         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9903         {
9904                 vec4_t layercolor;
9905                 int layertexrgbscale;
9906                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9907                 {
9908                         if (layerindex == 0)
9909                                 GL_AlphaTest(true);
9910                         else
9911                         {
9912                                 GL_AlphaTest(false);
9913                                 GL_DepthFunc(GL_EQUAL);
9914                         }
9915                 }
9916                 GL_DepthMask(layer->depthmask && writedepth);
9917                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9918                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9919                 {
9920                         layertexrgbscale = 4;
9921                         VectorScale(layer->color, 0.25f, layercolor);
9922                 }
9923                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9924                 {
9925                         layertexrgbscale = 2;
9926                         VectorScale(layer->color, 0.5f, layercolor);
9927                 }
9928                 else
9929                 {
9930                         layertexrgbscale = 1;
9931                         VectorScale(layer->color, 1.0f, layercolor);
9932                 }
9933                 layercolor[3] = layer->color[3];
9934                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9935                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9936                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9937                 switch (layer->type)
9938                 {
9939                 case TEXTURELAYERTYPE_LITTEXTURE:
9940                         // single-pass lightmapped texture with 2x rgbscale
9941                         R_Mesh_TexBind(0, r_texture_white);
9942                         R_Mesh_TexMatrix(0, NULL);
9943                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9944                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9945                         R_Mesh_TexBind(1, layer->texture);
9946                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9947                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9948                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9949                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9950                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9951                         else if (FAKELIGHT_ENABLED)
9952                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9953                         else if (rsurface.uselightmaptexture)
9954                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9955                         else
9956                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9957                         break;
9958                 case TEXTURELAYERTYPE_TEXTURE:
9959                         // singletexture unlit texture with transparency support
9960                         R_Mesh_TexBind(0, layer->texture);
9961                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9962                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9963                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9964                         R_Mesh_TexBind(1, 0);
9965                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9966                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9967                         break;
9968                 case TEXTURELAYERTYPE_FOG:
9969                         // singletexture fogging
9970                         if (layer->texture)
9971                         {
9972                                 R_Mesh_TexBind(0, layer->texture);
9973                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9974                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9975                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9976                         }
9977                         else
9978                         {
9979                                 R_Mesh_TexBind(0, 0);
9980                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9981                         }
9982                         R_Mesh_TexBind(1, 0);
9983                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9984                         // generate a color array for the fog pass
9985                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9986                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9987                         RSurf_DrawBatch();
9988                         break;
9989                 default:
9990                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9991                 }
9992         }
9993         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9994         {
9995                 GL_DepthFunc(GL_LEQUAL);
9996                 GL_AlphaTest(false);
9997         }
9998 }
9999
10000 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10001 {
10002         // OpenGL 1.1 - crusty old voodoo path
10003         qboolean applyfog;
10004         int layerindex;
10005         const texturelayer_t *layer;
10006         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);
10007         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10008
10009         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10010         {
10011                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10012                 {
10013                         if (layerindex == 0)
10014                                 GL_AlphaTest(true);
10015                         else
10016                         {
10017                                 GL_AlphaTest(false);
10018                                 GL_DepthFunc(GL_EQUAL);
10019                         }
10020                 }
10021                 GL_DepthMask(layer->depthmask && writedepth);
10022                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10023                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10024                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10025                 switch (layer->type)
10026                 {
10027                 case TEXTURELAYERTYPE_LITTEXTURE:
10028                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10029                         {
10030                                 // two-pass lit texture with 2x rgbscale
10031                                 // first the lightmap pass
10032                                 R_Mesh_TexBind(0, r_texture_white);
10033                                 R_Mesh_TexMatrix(0, NULL);
10034                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10035                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10036                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10037                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10038                                 else if (FAKELIGHT_ENABLED)
10039                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10040                                 else if (rsurface.uselightmaptexture)
10041                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10042                                 else
10043                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10044                                 // then apply the texture to it
10045                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10046                                 R_Mesh_TexBind(0, layer->texture);
10047                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10048                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10049                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10050                                 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);
10051                         }
10052                         else
10053                         {
10054                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10055                                 R_Mesh_TexBind(0, layer->texture);
10056                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10057                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10058                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10059                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10060                                         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);
10061                                 else if (FAKELIGHT_ENABLED)
10062                                         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);
10063                                 else
10064                                         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);
10065                         }
10066                         break;
10067                 case TEXTURELAYERTYPE_TEXTURE:
10068                         // singletexture unlit texture with transparency support
10069                         R_Mesh_TexBind(0, layer->texture);
10070                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10071                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10072                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10073                         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);
10074                         break;
10075                 case TEXTURELAYERTYPE_FOG:
10076                         // singletexture fogging
10077                         if (layer->texture)
10078                         {
10079                                 R_Mesh_TexBind(0, layer->texture);
10080                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10081                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10082                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10083                         }
10084                         else
10085                         {
10086                                 R_Mesh_TexBind(0, 0);
10087                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10088                         }
10089                         // generate a color array for the fog pass
10090                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10091                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10092                         RSurf_DrawBatch();
10093                         break;
10094                 default:
10095                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10096                 }
10097         }
10098         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10099         {
10100                 GL_DepthFunc(GL_LEQUAL);
10101                 GL_AlphaTest(false);
10102         }
10103 }
10104
10105 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10106 {
10107         int vi;
10108         int j;
10109         r_vertexgeneric_t *batchvertex;
10110         float c[4];
10111
10112 //      R_Mesh_ResetTextureState();
10113         R_SetupShader_Generic_NoTexture(false, false);
10114
10115         if(rsurface.texture && rsurface.texture->currentskinframe)
10116         {
10117                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10118                 c[3] *= rsurface.texture->currentalpha;
10119         }
10120         else
10121         {
10122                 c[0] = 1;
10123                 c[1] = 0;
10124                 c[2] = 1;
10125                 c[3] = 1;
10126         }
10127
10128         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10129         {
10130                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10131                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10132                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10133         }
10134
10135         // brighten it up (as texture value 127 means "unlit")
10136         c[0] *= 2 * r_refdef.view.colorscale;
10137         c[1] *= 2 * r_refdef.view.colorscale;
10138         c[2] *= 2 * r_refdef.view.colorscale;
10139
10140         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10141                 c[3] *= r_wateralpha.value;
10142
10143         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10144         {
10145                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10146                 GL_DepthMask(false);
10147         }
10148         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10149         {
10150                 GL_BlendFunc(GL_ONE, GL_ONE);
10151                 GL_DepthMask(false);
10152         }
10153         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10154         {
10155                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10156                 GL_DepthMask(false);
10157         }
10158         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10159         {
10160                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10161                 GL_DepthMask(false);
10162         }
10163         else
10164         {
10165                 GL_BlendFunc(GL_ONE, GL_ZERO);
10166                 GL_DepthMask(writedepth);
10167         }
10168
10169         if (r_showsurfaces.integer == 3)
10170         {
10171                 rsurface.passcolor4f = NULL;
10172
10173                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10174                 {
10175                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10176
10177                         rsurface.passcolor4f = NULL;
10178                         rsurface.passcolor4f_vertexbuffer = 0;
10179                         rsurface.passcolor4f_bufferoffset = 0;
10180                 }
10181                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10182                 {
10183                         qboolean applycolor = true;
10184                         float one = 1.0;
10185
10186                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10187
10188                         r_refdef.lightmapintensity = 1;
10189                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10190                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10191                 }
10192                 else if (FAKELIGHT_ENABLED)
10193                 {
10194                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10195
10196                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10197                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10198                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10199                 }
10200                 else
10201                 {
10202                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10203
10204                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10205                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10206                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10207                 }
10208
10209                 if(!rsurface.passcolor4f)
10210                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10211
10212                 RSurf_DrawBatch_GL11_ApplyAmbient();
10213                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10214                 if(r_refdef.fogenabled)
10215                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10216                 RSurf_DrawBatch_GL11_ClampColor();
10217
10218                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10219                 R_SetupShader_Generic_NoTexture(false, false);
10220                 RSurf_DrawBatch();
10221         }
10222         else if (!r_refdef.view.showdebug)
10223         {
10224                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10225                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10226                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10227                 {
10228                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10229                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10230                 }
10231                 R_Mesh_PrepareVertices_Generic_Unlock();
10232                 RSurf_DrawBatch();
10233         }
10234         else if (r_showsurfaces.integer == 4)
10235         {
10236                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10237                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10238                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10239                 {
10240                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10241                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10242                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10243                 }
10244                 R_Mesh_PrepareVertices_Generic_Unlock();
10245                 RSurf_DrawBatch();
10246         }
10247         else if (r_showsurfaces.integer == 2)
10248         {
10249                 const int *e;
10250                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10251                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10252                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10253                 {
10254                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10255                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10256                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10257                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10258                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10259                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10260                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10261                 }
10262                 R_Mesh_PrepareVertices_Generic_Unlock();
10263                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10264         }
10265         else
10266         {
10267                 int texturesurfaceindex;
10268                 int k;
10269                 const msurface_t *surface;
10270                 float surfacecolor4f[4];
10271                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10272                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10273                 vi = 0;
10274                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10275                 {
10276                         surface = texturesurfacelist[texturesurfaceindex];
10277                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10278                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10279                         for (j = 0;j < surface->num_vertices;j++)
10280                         {
10281                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10282                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10283                                 vi++;
10284                         }
10285                 }
10286                 R_Mesh_PrepareVertices_Generic_Unlock();
10287                 RSurf_DrawBatch();
10288         }
10289 }
10290
10291 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10292 {
10293         CHECKGLERROR
10294         RSurf_SetupDepthAndCulling();
10295         if (r_showsurfaces.integer)
10296         {
10297                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10298                 return;
10299         }
10300         switch (vid.renderpath)
10301         {
10302         case RENDERPATH_GL20:
10303         case RENDERPATH_D3D9:
10304         case RENDERPATH_D3D10:
10305         case RENDERPATH_D3D11:
10306         case RENDERPATH_SOFT:
10307         case RENDERPATH_GLES2:
10308                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10309                 break;
10310         case RENDERPATH_GL13:
10311         case RENDERPATH_GLES1:
10312                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10313                 break;
10314         case RENDERPATH_GL11:
10315                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10316                 break;
10317         }
10318         CHECKGLERROR
10319 }
10320
10321 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10322 {
10323         CHECKGLERROR
10324         RSurf_SetupDepthAndCulling();
10325         if (r_showsurfaces.integer)
10326         {
10327                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10328                 return;
10329         }
10330         switch (vid.renderpath)
10331         {
10332         case RENDERPATH_GL20:
10333         case RENDERPATH_D3D9:
10334         case RENDERPATH_D3D10:
10335         case RENDERPATH_D3D11:
10336         case RENDERPATH_SOFT:
10337         case RENDERPATH_GLES2:
10338                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10339                 break;
10340         case RENDERPATH_GL13:
10341         case RENDERPATH_GLES1:
10342                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10343                 break;
10344         case RENDERPATH_GL11:
10345                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10346                 break;
10347         }
10348         CHECKGLERROR
10349 }
10350
10351 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10352 {
10353         int i, j;
10354         int texturenumsurfaces, endsurface;
10355         texture_t *texture;
10356         const msurface_t *surface;
10357         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10358
10359         // if the model is static it doesn't matter what value we give for
10360         // wantnormals and wanttangents, so this logic uses only rules applicable
10361         // to a model, knowing that they are meaningless otherwise
10362         if (ent == r_refdef.scene.worldentity)
10363                 RSurf_ActiveWorldEntity();
10364         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10365                 RSurf_ActiveModelEntity(ent, false, false, false);
10366         else
10367         {
10368                 switch (vid.renderpath)
10369                 {
10370                 case RENDERPATH_GL20:
10371                 case RENDERPATH_D3D9:
10372                 case RENDERPATH_D3D10:
10373                 case RENDERPATH_D3D11:
10374                 case RENDERPATH_SOFT:
10375                 case RENDERPATH_GLES2:
10376                         RSurf_ActiveModelEntity(ent, true, true, false);
10377                         break;
10378                 case RENDERPATH_GL11:
10379                 case RENDERPATH_GL13:
10380                 case RENDERPATH_GLES1:
10381                         RSurf_ActiveModelEntity(ent, true, false, false);
10382                         break;
10383                 }
10384         }
10385
10386         if (r_transparentdepthmasking.integer)
10387         {
10388                 qboolean setup = false;
10389                 for (i = 0;i < numsurfaces;i = j)
10390                 {
10391                         j = i + 1;
10392                         surface = rsurface.modelsurfaces + surfacelist[i];
10393                         texture = surface->texture;
10394                         rsurface.texture = R_GetCurrentTexture(texture);
10395                         rsurface.lightmaptexture = NULL;
10396                         rsurface.deluxemaptexture = NULL;
10397                         rsurface.uselightmaptexture = false;
10398                         // scan ahead until we find a different texture
10399                         endsurface = min(i + 1024, numsurfaces);
10400                         texturenumsurfaces = 0;
10401                         texturesurfacelist[texturenumsurfaces++] = surface;
10402                         for (;j < endsurface;j++)
10403                         {
10404                                 surface = rsurface.modelsurfaces + surfacelist[j];
10405                                 if (texture != surface->texture)
10406                                         break;
10407                                 texturesurfacelist[texturenumsurfaces++] = surface;
10408                         }
10409                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10410                                 continue;
10411                         // render the range of surfaces as depth
10412                         if (!setup)
10413                         {
10414                                 setup = true;
10415                                 GL_ColorMask(0,0,0,0);
10416                                 GL_Color(1,1,1,1);
10417                                 GL_DepthTest(true);
10418                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10419                                 GL_DepthMask(true);
10420 //                              R_Mesh_ResetTextureState();
10421                                 R_SetupShader_DepthOrShadow(false, false);
10422                         }
10423                         RSurf_SetupDepthAndCulling();
10424                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10425                         if (rsurface.batchvertex3fbuffer)
10426                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10427                         else
10428                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10429                         RSurf_DrawBatch();
10430                 }
10431                 if (setup)
10432                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10433         }
10434
10435         for (i = 0;i < numsurfaces;i = j)
10436         {
10437                 j = i + 1;
10438                 surface = rsurface.modelsurfaces + surfacelist[i];
10439                 texture = surface->texture;
10440                 rsurface.texture = R_GetCurrentTexture(texture);
10441                 // scan ahead until we find a different texture
10442                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10443                 texturenumsurfaces = 0;
10444                 texturesurfacelist[texturenumsurfaces++] = surface;
10445                 if(FAKELIGHT_ENABLED)
10446                 {
10447                         rsurface.lightmaptexture = NULL;
10448                         rsurface.deluxemaptexture = NULL;
10449                         rsurface.uselightmaptexture = false;
10450                         for (;j < endsurface;j++)
10451                         {
10452                                 surface = rsurface.modelsurfaces + surfacelist[j];
10453                                 if (texture != surface->texture)
10454                                         break;
10455                                 texturesurfacelist[texturenumsurfaces++] = surface;
10456                         }
10457                 }
10458                 else
10459                 {
10460                         rsurface.lightmaptexture = surface->lightmaptexture;
10461                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10462                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10463                         for (;j < endsurface;j++)
10464                         {
10465                                 surface = rsurface.modelsurfaces + surfacelist[j];
10466                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10467                                         break;
10468                                 texturesurfacelist[texturenumsurfaces++] = surface;
10469                         }
10470                 }
10471                 // render the range of surfaces
10472                 if (ent == r_refdef.scene.worldentity)
10473                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10474                 else
10475                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10476         }
10477         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10478 }
10479
10480 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10481 {
10482         // transparent surfaces get pushed off into the transparent queue
10483         int surfacelistindex;
10484         const msurface_t *surface;
10485         vec3_t tempcenter, center;
10486         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10487         {
10488                 surface = texturesurfacelist[surfacelistindex];
10489                 if (r_transparent_sortsurfacesbynearest.integer)
10490                 {
10491                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10492                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10493                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10494                 }
10495                 else
10496                 {
10497                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10498                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10499                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10500                 }
10501                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10502                 if (rsurface.entity->transparent_offset) // transparent offset
10503                 {
10504                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10505                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10506                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10507                 }
10508                 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);
10509         }
10510 }
10511
10512 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10513 {
10514         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10515                 return;
10516         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10517                 return;
10518         RSurf_SetupDepthAndCulling();
10519         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10520         if (rsurface.batchvertex3fbuffer)
10521                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10522         else
10523                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10524         RSurf_DrawBatch();
10525 }
10526
10527 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10528 {
10529         CHECKGLERROR
10530         if (depthonly)
10531                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10532         else if (prepass)
10533         {
10534                 if (!rsurface.texture->currentnumlayers)
10535                         return;
10536                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10537                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10538                 else
10539                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10540         }
10541         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10542                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10543         else if (!rsurface.texture->currentnumlayers)
10544                 return;
10545         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10546         {
10547                 // in the deferred case, transparent surfaces were queued during prepass
10548                 if (!r_shadow_usingdeferredprepass)
10549                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10550         }
10551         else
10552         {
10553                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10554                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10555         }
10556         CHECKGLERROR
10557 }
10558
10559 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10560 {
10561         int i, j;
10562         texture_t *texture;
10563         R_FrameData_SetMark();
10564         // break the surface list down into batches by texture and use of lightmapping
10565         for (i = 0;i < numsurfaces;i = j)
10566         {
10567                 j = i + 1;
10568                 // texture is the base texture pointer, rsurface.texture is the
10569                 // current frame/skin the texture is directing us to use (for example
10570                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10571                 // use skin 1 instead)
10572                 texture = surfacelist[i]->texture;
10573                 rsurface.texture = R_GetCurrentTexture(texture);
10574                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10575                 {
10576                         // if this texture is not the kind we want, skip ahead to the next one
10577                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10578                                 ;
10579                         continue;
10580                 }
10581                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10582                 {
10583                         rsurface.lightmaptexture = NULL;
10584                         rsurface.deluxemaptexture = NULL;
10585                         rsurface.uselightmaptexture = false;
10586                         // simply scan ahead until we find a different texture or lightmap state
10587                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10588                                 ;
10589                 }
10590                 else
10591                 {
10592                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10593                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10594                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10595                         // simply scan ahead until we find a different texture or lightmap state
10596                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10597                                 ;
10598                 }
10599                 // render the range of surfaces
10600                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10601         }
10602         R_FrameData_ReturnToMark();
10603 }
10604
10605 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10606 {
10607         CHECKGLERROR
10608         if (depthonly)
10609                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10610         else if (prepass)
10611         {
10612                 if (!rsurface.texture->currentnumlayers)
10613                         return;
10614                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10615                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10616                 else
10617                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10618         }
10619         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10620                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10621         else if (!rsurface.texture->currentnumlayers)
10622                 return;
10623         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10624         {
10625                 // in the deferred case, transparent surfaces were queued during prepass
10626                 if (!r_shadow_usingdeferredprepass)
10627                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10628         }
10629         else
10630         {
10631                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10632                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10633         }
10634         CHECKGLERROR
10635 }
10636
10637 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10638 {
10639         int i, j;
10640         texture_t *texture;
10641         R_FrameData_SetMark();
10642         // break the surface list down into batches by texture and use of lightmapping
10643         for (i = 0;i < numsurfaces;i = j)
10644         {
10645                 j = i + 1;
10646                 // texture is the base texture pointer, rsurface.texture is the
10647                 // current frame/skin the texture is directing us to use (for example
10648                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10649                 // use skin 1 instead)
10650                 texture = surfacelist[i]->texture;
10651                 rsurface.texture = R_GetCurrentTexture(texture);
10652                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10653                 {
10654                         // if this texture is not the kind we want, skip ahead to the next one
10655                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10656                                 ;
10657                         continue;
10658                 }
10659                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10660                 {
10661                         rsurface.lightmaptexture = NULL;
10662                         rsurface.deluxemaptexture = NULL;
10663                         rsurface.uselightmaptexture = false;
10664                         // simply scan ahead until we find a different texture or lightmap state
10665                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10666                                 ;
10667                 }
10668                 else
10669                 {
10670                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10671                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10672                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10673                         // simply scan ahead until we find a different texture or lightmap state
10674                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10675                                 ;
10676                 }
10677                 // render the range of surfaces
10678                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10679         }
10680         R_FrameData_ReturnToMark();
10681 }
10682
10683 float locboxvertex3f[6*4*3] =
10684 {
10685         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10686         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10687         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10688         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10689         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10690         1,0,0, 0,0,0, 0,1,0, 1,1,0
10691 };
10692
10693 unsigned short locboxelements[6*2*3] =
10694 {
10695          0, 1, 2, 0, 2, 3,
10696          4, 5, 6, 4, 6, 7,
10697          8, 9,10, 8,10,11,
10698         12,13,14, 12,14,15,
10699         16,17,18, 16,18,19,
10700         20,21,22, 20,22,23
10701 };
10702
10703 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10704 {
10705         int i, j;
10706         cl_locnode_t *loc = (cl_locnode_t *)ent;
10707         vec3_t mins, size;
10708         float vertex3f[6*4*3];
10709         CHECKGLERROR
10710         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10711         GL_DepthMask(false);
10712         GL_DepthRange(0, 1);
10713         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10714         GL_DepthTest(true);
10715         GL_CullFace(GL_NONE);
10716         R_EntityMatrix(&identitymatrix);
10717
10718 //      R_Mesh_ResetTextureState();
10719
10720         i = surfacelist[0];
10721         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10722                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10723                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10724                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10725
10726         if (VectorCompare(loc->mins, loc->maxs))
10727         {
10728                 VectorSet(size, 2, 2, 2);
10729                 VectorMA(loc->mins, -0.5f, size, mins);
10730         }
10731         else
10732         {
10733                 VectorCopy(loc->mins, mins);
10734                 VectorSubtract(loc->maxs, loc->mins, size);
10735         }
10736
10737         for (i = 0;i < 6*4*3;)
10738                 for (j = 0;j < 3;j++, i++)
10739                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10740
10741         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10742         R_SetupShader_Generic_NoTexture(false, false);
10743         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10744 }
10745
10746 void R_DrawLocs(void)
10747 {
10748         int index;
10749         cl_locnode_t *loc, *nearestloc;
10750         vec3_t center;
10751         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10752         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10753         {
10754                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10755                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10756         }
10757 }
10758
10759 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10760 {
10761         if (decalsystem->decals)
10762                 Mem_Free(decalsystem->decals);
10763         memset(decalsystem, 0, sizeof(*decalsystem));
10764 }
10765
10766 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)
10767 {
10768         tridecal_t *decal;
10769         tridecal_t *decals;
10770         int i;
10771
10772         // expand or initialize the system
10773         if (decalsystem->maxdecals <= decalsystem->numdecals)
10774         {
10775                 decalsystem_t old = *decalsystem;
10776                 qboolean useshortelements;
10777                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10778                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10779                 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)));
10780                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10781                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10782                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10783                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10784                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10785                 if (decalsystem->numdecals)
10786                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10787                 if (old.decals)
10788                         Mem_Free(old.decals);
10789                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10790                         decalsystem->element3i[i] = i;
10791                 if (useshortelements)
10792                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10793                                 decalsystem->element3s[i] = i;
10794         }
10795
10796         // grab a decal and search for another free slot for the next one
10797         decals = decalsystem->decals;
10798         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10799         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10800                 ;
10801         decalsystem->freedecal = i;
10802         if (decalsystem->numdecals <= i)
10803                 decalsystem->numdecals = i + 1;
10804
10805         // initialize the decal
10806         decal->lived = 0;
10807         decal->triangleindex = triangleindex;
10808         decal->surfaceindex = surfaceindex;
10809         decal->decalsequence = decalsequence;
10810         decal->color4f[0][0] = c0[0];
10811         decal->color4f[0][1] = c0[1];
10812         decal->color4f[0][2] = c0[2];
10813         decal->color4f[0][3] = 1;
10814         decal->color4f[1][0] = c1[0];
10815         decal->color4f[1][1] = c1[1];
10816         decal->color4f[1][2] = c1[2];
10817         decal->color4f[1][3] = 1;
10818         decal->color4f[2][0] = c2[0];
10819         decal->color4f[2][1] = c2[1];
10820         decal->color4f[2][2] = c2[2];
10821         decal->color4f[2][3] = 1;
10822         decal->vertex3f[0][0] = v0[0];
10823         decal->vertex3f[0][1] = v0[1];
10824         decal->vertex3f[0][2] = v0[2];
10825         decal->vertex3f[1][0] = v1[0];
10826         decal->vertex3f[1][1] = v1[1];
10827         decal->vertex3f[1][2] = v1[2];
10828         decal->vertex3f[2][0] = v2[0];
10829         decal->vertex3f[2][1] = v2[1];
10830         decal->vertex3f[2][2] = v2[2];
10831         decal->texcoord2f[0][0] = t0[0];
10832         decal->texcoord2f[0][1] = t0[1];
10833         decal->texcoord2f[1][0] = t1[0];
10834         decal->texcoord2f[1][1] = t1[1];
10835         decal->texcoord2f[2][0] = t2[0];
10836         decal->texcoord2f[2][1] = t2[1];
10837         TriangleNormal(v0, v1, v2, decal->plane);
10838         VectorNormalize(decal->plane);
10839         decal->plane[3] = DotProduct(v0, decal->plane);
10840 }
10841
10842 extern cvar_t cl_decals_bias;
10843 extern cvar_t cl_decals_models;
10844 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10845 // baseparms, parms, temps
10846 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)
10847 {
10848         int cornerindex;
10849         int index;
10850         float v[9][3];
10851         const float *vertex3f;
10852         const float *normal3f;
10853         int numpoints;
10854         float points[2][9][3];
10855         float temp[3];
10856         float tc[9][2];
10857         float f;
10858         float c[9][4];
10859         const int *e;
10860
10861         e = rsurface.modelelement3i + 3*triangleindex;
10862
10863         vertex3f = rsurface.modelvertex3f;
10864         normal3f = rsurface.modelnormal3f;
10865
10866         if (normal3f)
10867         {
10868                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10869                 {
10870                         index = 3*e[cornerindex];
10871                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10872                 }
10873         }
10874         else
10875         {
10876                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10877                 {
10878                         index = 3*e[cornerindex];
10879                         VectorCopy(vertex3f + index, v[cornerindex]);
10880                 }
10881         }
10882
10883         // cull backfaces
10884         //TriangleNormal(v[0], v[1], v[2], normal);
10885         //if (DotProduct(normal, localnormal) < 0.0f)
10886         //      continue;
10887         // clip by each of the box planes formed from the projection matrix
10888         // if anything survives, we emit the decal
10889         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]);
10890         if (numpoints < 3)
10891                 return;
10892         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]);
10893         if (numpoints < 3)
10894                 return;
10895         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]);
10896         if (numpoints < 3)
10897                 return;
10898         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]);
10899         if (numpoints < 3)
10900                 return;
10901         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]);
10902         if (numpoints < 3)
10903                 return;
10904         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]);
10905         if (numpoints < 3)
10906                 return;
10907         // some part of the triangle survived, so we have to accept it...
10908         if (dynamic)
10909         {
10910                 // dynamic always uses the original triangle
10911                 numpoints = 3;
10912                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10913                 {
10914                         index = 3*e[cornerindex];
10915                         VectorCopy(vertex3f + index, v[cornerindex]);
10916                 }
10917         }
10918         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10919         {
10920                 // convert vertex positions to texcoords
10921                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10922                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10923                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10924                 // calculate distance fade from the projection origin
10925                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10926                 f = bound(0.0f, f, 1.0f);
10927                 c[cornerindex][0] = r * f;
10928                 c[cornerindex][1] = g * f;
10929                 c[cornerindex][2] = b * f;
10930                 c[cornerindex][3] = 1.0f;
10931                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10932         }
10933         if (dynamic)
10934                 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);
10935         else
10936                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10937                         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);
10938 }
10939 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)
10940 {
10941         matrix4x4_t projection;
10942         decalsystem_t *decalsystem;
10943         qboolean dynamic;
10944         dp_model_t *model;
10945         const msurface_t *surface;
10946         const msurface_t *surfaces;
10947         const int *surfacelist;
10948         const texture_t *texture;
10949         int numtriangles;
10950         int numsurfacelist;
10951         int surfacelistindex;
10952         int surfaceindex;
10953         int triangleindex;
10954         float localorigin[3];
10955         float localnormal[3];
10956         float localmins[3];
10957         float localmaxs[3];
10958         float localsize;
10959         //float normal[3];
10960         float planes[6][4];
10961         float angles[3];
10962         bih_t *bih;
10963         int bih_triangles_count;
10964         int bih_triangles[256];
10965         int bih_surfaces[256];
10966
10967         decalsystem = &ent->decalsystem;
10968         model = ent->model;
10969         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10970         {
10971                 R_DecalSystem_Reset(&ent->decalsystem);
10972                 return;
10973         }
10974
10975         if (!model->brush.data_leafs && !cl_decals_models.integer)
10976         {
10977                 if (decalsystem->model)
10978                         R_DecalSystem_Reset(decalsystem);
10979                 return;
10980         }
10981
10982         if (decalsystem->model != model)
10983                 R_DecalSystem_Reset(decalsystem);
10984         decalsystem->model = model;
10985
10986         RSurf_ActiveModelEntity(ent, true, false, false);
10987
10988         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10989         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10990         VectorNormalize(localnormal);
10991         localsize = worldsize*rsurface.inversematrixscale;
10992         localmins[0] = localorigin[0] - localsize;
10993         localmins[1] = localorigin[1] - localsize;
10994         localmins[2] = localorigin[2] - localsize;
10995         localmaxs[0] = localorigin[0] + localsize;
10996         localmaxs[1] = localorigin[1] + localsize;
10997         localmaxs[2] = localorigin[2] + localsize;
10998
10999         //VectorCopy(localnormal, planes[4]);
11000         //VectorVectors(planes[4], planes[2], planes[0]);
11001         AnglesFromVectors(angles, localnormal, NULL, false);
11002         AngleVectors(angles, planes[0], planes[2], planes[4]);
11003         VectorNegate(planes[0], planes[1]);
11004         VectorNegate(planes[2], planes[3]);
11005         VectorNegate(planes[4], planes[5]);
11006         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11007         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11008         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11009         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11010         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11011         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11012
11013 #if 1
11014 // works
11015 {
11016         matrix4x4_t forwardprojection;
11017         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11018         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11019 }
11020 #else
11021 // broken
11022 {
11023         float projectionvector[4][3];
11024         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11025         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11026         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11027         projectionvector[0][0] = planes[0][0] * ilocalsize;
11028         projectionvector[0][1] = planes[1][0] * ilocalsize;
11029         projectionvector[0][2] = planes[2][0] * ilocalsize;
11030         projectionvector[1][0] = planes[0][1] * ilocalsize;
11031         projectionvector[1][1] = planes[1][1] * ilocalsize;
11032         projectionvector[1][2] = planes[2][1] * ilocalsize;
11033         projectionvector[2][0] = planes[0][2] * ilocalsize;
11034         projectionvector[2][1] = planes[1][2] * ilocalsize;
11035         projectionvector[2][2] = planes[2][2] * ilocalsize;
11036         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11037         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11038         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11039         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11040 }
11041 #endif
11042
11043         dynamic = model->surfmesh.isanimated;
11044         numsurfacelist = model->nummodelsurfaces;
11045         surfacelist = model->sortedmodelsurfaces;
11046         surfaces = model->data_surfaces;
11047
11048         bih = NULL;
11049         bih_triangles_count = -1;
11050         if(!dynamic)
11051         {
11052                 if(model->render_bih.numleafs)
11053                         bih = &model->render_bih;
11054                 else if(model->collision_bih.numleafs)
11055                         bih = &model->collision_bih;
11056         }
11057         if(bih)
11058                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11059         if(bih_triangles_count == 0)
11060                 return;
11061         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11062                 return;
11063         if(bih_triangles_count > 0)
11064         {
11065                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11066                 {
11067                         surfaceindex = bih_surfaces[triangleindex];
11068                         surface = surfaces + surfaceindex;
11069                         texture = surface->texture;
11070                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11071                                 continue;
11072                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11073                                 continue;
11074                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11075                 }
11076         }
11077         else
11078         {
11079                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11080                 {
11081                         surfaceindex = surfacelist[surfacelistindex];
11082                         surface = surfaces + surfaceindex;
11083                         // check cull box first because it rejects more than any other check
11084                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11085                                 continue;
11086                         // skip transparent surfaces
11087                         texture = surface->texture;
11088                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11089                                 continue;
11090                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11091                                 continue;
11092                         numtriangles = surface->num_triangles;
11093                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11094                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11095                 }
11096         }
11097 }
11098
11099 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11100 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)
11101 {
11102         int renderentityindex;
11103         float worldmins[3];
11104         float worldmaxs[3];
11105         entity_render_t *ent;
11106
11107         if (!cl_decals_newsystem.integer)
11108                 return;
11109
11110         worldmins[0] = worldorigin[0] - worldsize;
11111         worldmins[1] = worldorigin[1] - worldsize;
11112         worldmins[2] = worldorigin[2] - worldsize;
11113         worldmaxs[0] = worldorigin[0] + worldsize;
11114         worldmaxs[1] = worldorigin[1] + worldsize;
11115         worldmaxs[2] = worldorigin[2] + worldsize;
11116
11117         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11118
11119         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11120         {
11121                 ent = r_refdef.scene.entities[renderentityindex];
11122                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11123                         continue;
11124
11125                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11126         }
11127 }
11128
11129 typedef struct r_decalsystem_splatqueue_s
11130 {
11131         vec3_t worldorigin;
11132         vec3_t worldnormal;
11133         float color[4];
11134         float tcrange[4];
11135         float worldsize;
11136         int decalsequence;
11137 }
11138 r_decalsystem_splatqueue_t;
11139
11140 int r_decalsystem_numqueued = 0;
11141 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11142
11143 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)
11144 {
11145         r_decalsystem_splatqueue_t *queue;
11146
11147         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11148                 return;
11149
11150         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11151         VectorCopy(worldorigin, queue->worldorigin);
11152         VectorCopy(worldnormal, queue->worldnormal);
11153         Vector4Set(queue->color, r, g, b, a);
11154         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11155         queue->worldsize = worldsize;
11156         queue->decalsequence = cl.decalsequence++;
11157 }
11158
11159 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11160 {
11161         int i;
11162         r_decalsystem_splatqueue_t *queue;
11163
11164         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11165                 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);
11166         r_decalsystem_numqueued = 0;
11167 }
11168
11169 extern cvar_t cl_decals_max;
11170 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11171 {
11172         int i;
11173         decalsystem_t *decalsystem = &ent->decalsystem;
11174         int numdecals;
11175         int killsequence;
11176         tridecal_t *decal;
11177         float frametime;
11178         float lifetime;
11179
11180         if (!decalsystem->numdecals)
11181                 return;
11182
11183         if (r_showsurfaces.integer)
11184                 return;
11185
11186         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11187         {
11188                 R_DecalSystem_Reset(decalsystem);
11189                 return;
11190         }
11191
11192         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11193         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11194
11195         if (decalsystem->lastupdatetime)
11196                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11197         else
11198                 frametime = 0;
11199         decalsystem->lastupdatetime = r_refdef.scene.time;
11200         numdecals = decalsystem->numdecals;
11201
11202         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11203         {
11204                 if (decal->color4f[0][3])
11205                 {
11206                         decal->lived += frametime;
11207                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11208                         {
11209                                 memset(decal, 0, sizeof(*decal));
11210                                 if (decalsystem->freedecal > i)
11211                                         decalsystem->freedecal = i;
11212                         }
11213                 }
11214         }
11215         decal = decalsystem->decals;
11216         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11217                 numdecals--;
11218
11219         // collapse the array by shuffling the tail decals into the gaps
11220         for (;;)
11221         {
11222                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11223                         decalsystem->freedecal++;
11224                 if (decalsystem->freedecal == numdecals)
11225                         break;
11226                 decal[decalsystem->freedecal] = decal[--numdecals];
11227         }
11228
11229         decalsystem->numdecals = numdecals;
11230
11231         if (numdecals <= 0)
11232         {
11233                 // if there are no decals left, reset decalsystem
11234                 R_DecalSystem_Reset(decalsystem);
11235         }
11236 }
11237
11238 extern skinframe_t *decalskinframe;
11239 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11240 {
11241         int i;
11242         decalsystem_t *decalsystem = &ent->decalsystem;
11243         int numdecals;
11244         tridecal_t *decal;
11245         float faderate;
11246         float alpha;
11247         float *v3f;
11248         float *c4f;
11249         float *t2f;
11250         const int *e;
11251         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11252         int numtris = 0;
11253
11254         numdecals = decalsystem->numdecals;
11255         if (!numdecals)
11256                 return;
11257
11258         if (r_showsurfaces.integer)
11259                 return;
11260
11261         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11262         {
11263                 R_DecalSystem_Reset(decalsystem);
11264                 return;
11265         }
11266
11267         // if the model is static it doesn't matter what value we give for
11268         // wantnormals and wanttangents, so this logic uses only rules applicable
11269         // to a model, knowing that they are meaningless otherwise
11270         if (ent == r_refdef.scene.worldentity)
11271                 RSurf_ActiveWorldEntity();
11272         else
11273                 RSurf_ActiveModelEntity(ent, false, false, false);
11274
11275         decalsystem->lastupdatetime = r_refdef.scene.time;
11276
11277         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11278
11279         // update vertex positions for animated models
11280         v3f = decalsystem->vertex3f;
11281         c4f = decalsystem->color4f;
11282         t2f = decalsystem->texcoord2f;
11283         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11284         {
11285                 if (!decal->color4f[0][3])
11286                         continue;
11287
11288                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11289                         continue;
11290
11291                 // skip backfaces
11292                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11293                         continue;
11294
11295                 // update color values for fading decals
11296                 if (decal->lived >= cl_decals_time.value)
11297                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11298                 else
11299                         alpha = 1.0f;
11300
11301                 c4f[ 0] = decal->color4f[0][0] * alpha;
11302                 c4f[ 1] = decal->color4f[0][1] * alpha;
11303                 c4f[ 2] = decal->color4f[0][2] * alpha;
11304                 c4f[ 3] = 1;
11305                 c4f[ 4] = decal->color4f[1][0] * alpha;
11306                 c4f[ 5] = decal->color4f[1][1] * alpha;
11307                 c4f[ 6] = decal->color4f[1][2] * alpha;
11308                 c4f[ 7] = 1;
11309                 c4f[ 8] = decal->color4f[2][0] * alpha;
11310                 c4f[ 9] = decal->color4f[2][1] * alpha;
11311                 c4f[10] = decal->color4f[2][2] * alpha;
11312                 c4f[11] = 1;
11313
11314                 t2f[0] = decal->texcoord2f[0][0];
11315                 t2f[1] = decal->texcoord2f[0][1];
11316                 t2f[2] = decal->texcoord2f[1][0];
11317                 t2f[3] = decal->texcoord2f[1][1];
11318                 t2f[4] = decal->texcoord2f[2][0];
11319                 t2f[5] = decal->texcoord2f[2][1];
11320
11321                 // update vertex positions for animated models
11322                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11323                 {
11324                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11325                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11326                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11327                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11328                 }
11329                 else
11330                 {
11331                         VectorCopy(decal->vertex3f[0], v3f);
11332                         VectorCopy(decal->vertex3f[1], v3f + 3);
11333                         VectorCopy(decal->vertex3f[2], v3f + 6);
11334                 }
11335
11336                 if (r_refdef.fogenabled)
11337                 {
11338                         alpha = RSurf_FogVertex(v3f);
11339                         VectorScale(c4f, alpha, c4f);
11340                         alpha = RSurf_FogVertex(v3f + 3);
11341                         VectorScale(c4f + 4, alpha, c4f + 4);
11342                         alpha = RSurf_FogVertex(v3f + 6);
11343                         VectorScale(c4f + 8, alpha, c4f + 8);
11344                 }
11345
11346                 v3f += 9;
11347                 c4f += 12;
11348                 t2f += 6;
11349                 numtris++;
11350         }
11351
11352         if (numtris > 0)
11353         {
11354                 r_refdef.stats.drawndecals += numtris;
11355
11356                 // now render the decals all at once
11357                 // (this assumes they all use one particle font texture!)
11358                 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);
11359 //              R_Mesh_ResetTextureState();
11360                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11361                 GL_DepthMask(false);
11362                 GL_DepthRange(0, 1);
11363                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11364                 GL_DepthTest(true);
11365                 GL_CullFace(GL_NONE);
11366                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11367                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11368                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11369         }
11370 }
11371
11372 static void R_DrawModelDecals(void)
11373 {
11374         int i, numdecals;
11375
11376         // fade faster when there are too many decals
11377         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11378         for (i = 0;i < r_refdef.scene.numentities;i++)
11379                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11380
11381         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11382         for (i = 0;i < r_refdef.scene.numentities;i++)
11383                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11384                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11385
11386         R_DecalSystem_ApplySplatEntitiesQueue();
11387
11388         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11389         for (i = 0;i < r_refdef.scene.numentities;i++)
11390                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11391
11392         r_refdef.stats.totaldecals += numdecals;
11393
11394         if (r_showsurfaces.integer)
11395                 return;
11396
11397         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11398
11399         for (i = 0;i < r_refdef.scene.numentities;i++)
11400         {
11401                 if (!r_refdef.viewcache.entityvisible[i])
11402                         continue;
11403                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11404                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11405         }
11406 }
11407
11408 extern cvar_t mod_collision_bih;
11409 static void R_DrawDebugModel(void)
11410 {
11411         entity_render_t *ent = rsurface.entity;
11412         int i, j, k, l, flagsmask;
11413         const msurface_t *surface;
11414         dp_model_t *model = ent->model;
11415         vec3_t v;
11416
11417         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11418                 return;
11419
11420         if (r_showoverdraw.value > 0)
11421         {
11422                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11423                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11424                 R_SetupShader_Generic_NoTexture(false, false);
11425                 GL_DepthTest(false);
11426                 GL_DepthMask(false);
11427                 GL_DepthRange(0, 1);
11428                 GL_BlendFunc(GL_ONE, GL_ONE);
11429                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11430                 {
11431                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11432                                 continue;
11433                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11434                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11435                         {
11436                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11437                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11438                                 if (!rsurface.texture->currentlayers->depthmask)
11439                                         GL_Color(c, 0, 0, 1.0f);
11440                                 else if (ent == r_refdef.scene.worldentity)
11441                                         GL_Color(c, c, c, 1.0f);
11442                                 else
11443                                         GL_Color(0, c, 0, 1.0f);
11444                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11445                                 RSurf_DrawBatch();
11446                         }
11447                 }
11448                 rsurface.texture = NULL;
11449         }
11450
11451         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11452
11453 //      R_Mesh_ResetTextureState();
11454         R_SetupShader_Generic_NoTexture(false, false);
11455         GL_DepthRange(0, 1);
11456         GL_DepthTest(!r_showdisabledepthtest.integer);
11457         GL_DepthMask(false);
11458         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11459
11460         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11461         {
11462                 int triangleindex;
11463                 int bihleafindex;
11464                 qboolean cullbox = false;
11465                 const q3mbrush_t *brush;
11466                 const bih_t *bih = &model->collision_bih;
11467                 const bih_leaf_t *bihleaf;
11468                 float vertex3f[3][3];
11469                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11470                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11471                 {
11472                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11473                                 continue;
11474                         switch (bihleaf->type)
11475                         {
11476                         case BIH_BRUSH:
11477                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11478                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11479                                 {
11480                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11481                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11482                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11483                                 }
11484                                 break;
11485                         case BIH_COLLISIONTRIANGLE:
11486                                 triangleindex = bihleaf->itemindex;
11487                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11488                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11489                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11490                                 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);
11491                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11492                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11493                                 break;
11494                         case BIH_RENDERTRIANGLE:
11495                                 triangleindex = bihleaf->itemindex;
11496                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11497                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11498                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11499                                 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);
11500                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11501                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11502                                 break;
11503                         }
11504                 }
11505         }
11506
11507         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11508
11509 #ifndef USE_GLES2
11510         if (r_showtris.integer && qglPolygonMode)
11511         {
11512                 if (r_showdisabledepthtest.integer)
11513                 {
11514                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11515                         GL_DepthMask(false);
11516                 }
11517                 else
11518                 {
11519                         GL_BlendFunc(GL_ONE, GL_ZERO);
11520                         GL_DepthMask(true);
11521                 }
11522                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11523                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11524                 {
11525                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11526                                 continue;
11527                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11528                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11529                         {
11530                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11531                                 if (!rsurface.texture->currentlayers->depthmask)
11532                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11533                                 else if (ent == r_refdef.scene.worldentity)
11534                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11535                                 else
11536                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11537                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11538                                 RSurf_DrawBatch();
11539                         }
11540                 }
11541                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11542                 rsurface.texture = NULL;
11543         }
11544
11545         if (r_shownormals.value != 0 && qglBegin)
11546         {
11547                 if (r_showdisabledepthtest.integer)
11548                 {
11549                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11550                         GL_DepthMask(false);
11551                 }
11552                 else
11553                 {
11554                         GL_BlendFunc(GL_ONE, GL_ZERO);
11555                         GL_DepthMask(true);
11556                 }
11557                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11558                 {
11559                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11560                                 continue;
11561                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11562                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11563                         {
11564                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11565                                 qglBegin(GL_LINES);
11566                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11567                                 {
11568                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11569                                         {
11570                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11571                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11572                                                 qglVertex3f(v[0], v[1], v[2]);
11573                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11574                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11575                                                 qglVertex3f(v[0], v[1], v[2]);
11576                                         }
11577                                 }
11578                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11579                                 {
11580                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11581                                         {
11582                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11583                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11584                                                 qglVertex3f(v[0], v[1], v[2]);
11585                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11586                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11587                                                 qglVertex3f(v[0], v[1], v[2]);
11588                                         }
11589                                 }
11590                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11591                                 {
11592                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11593                                         {
11594                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11595                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11596                                                 qglVertex3f(v[0], v[1], v[2]);
11597                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11598                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11599                                                 qglVertex3f(v[0], v[1], v[2]);
11600                                         }
11601                                 }
11602                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11603                                 {
11604                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11605                                         {
11606                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11607                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11608                                                 qglVertex3f(v[0], v[1], v[2]);
11609                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11610                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11611                                                 qglVertex3f(v[0], v[1], v[2]);
11612                                         }
11613                                 }
11614                                 qglEnd();
11615                                 CHECKGLERROR
11616                         }
11617                 }
11618                 rsurface.texture = NULL;
11619         }
11620 #endif
11621 }
11622
11623 int r_maxsurfacelist = 0;
11624 const msurface_t **r_surfacelist = NULL;
11625 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11626 {
11627         int i, j, endj, flagsmask;
11628         dp_model_t *model = r_refdef.scene.worldmodel;
11629         msurface_t *surfaces;
11630         unsigned char *update;
11631         int numsurfacelist = 0;
11632         if (model == NULL)
11633                 return;
11634
11635         if (r_maxsurfacelist < model->num_surfaces)
11636         {
11637                 r_maxsurfacelist = model->num_surfaces;
11638                 if (r_surfacelist)
11639                         Mem_Free((msurface_t**)r_surfacelist);
11640                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11641         }
11642
11643         RSurf_ActiveWorldEntity();
11644
11645         surfaces = model->data_surfaces;
11646         update = model->brushq1.lightmapupdateflags;
11647
11648         // update light styles on this submodel
11649         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11650         {
11651                 model_brush_lightstyleinfo_t *style;
11652                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11653                 {
11654                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11655                         {
11656                                 int *list = style->surfacelist;
11657                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11658                                 for (j = 0;j < style->numsurfaces;j++)
11659                                         update[list[j]] = true;
11660                         }
11661                 }
11662         }
11663
11664         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11665
11666         if (debug)
11667         {
11668                 R_DrawDebugModel();
11669                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11670                 return;
11671         }
11672
11673         rsurface.lightmaptexture = NULL;
11674         rsurface.deluxemaptexture = NULL;
11675         rsurface.uselightmaptexture = false;
11676         rsurface.texture = NULL;
11677         rsurface.rtlight = NULL;
11678         numsurfacelist = 0;
11679         // add visible surfaces to draw list
11680         for (i = 0;i < model->nummodelsurfaces;i++)
11681         {
11682                 j = model->sortedmodelsurfaces[i];
11683                 if (r_refdef.viewcache.world_surfacevisible[j])
11684                         r_surfacelist[numsurfacelist++] = surfaces + j;
11685         }
11686         // update lightmaps if needed
11687         if (model->brushq1.firstrender)
11688         {
11689                 model->brushq1.firstrender = false;
11690                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11691                         if (update[j])
11692                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11693         }
11694         else if (update)
11695         {
11696                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11697                         if (r_refdef.viewcache.world_surfacevisible[j])
11698                                 if (update[j])
11699                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11700         }
11701         // don't do anything if there were no surfaces
11702         if (!numsurfacelist)
11703         {
11704                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11705                 return;
11706         }
11707         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11708
11709         // add to stats if desired
11710         if (r_speeds.integer && !skysurfaces && !depthonly)
11711         {
11712                 r_refdef.stats.world_surfaces += numsurfacelist;
11713                 for (j = 0;j < numsurfacelist;j++)
11714                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11715         }
11716
11717         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11718 }
11719
11720 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11721 {
11722         int i, j, endj, flagsmask;
11723         dp_model_t *model = ent->model;
11724         msurface_t *surfaces;
11725         unsigned char *update;
11726         int numsurfacelist = 0;
11727         if (model == NULL)
11728                 return;
11729
11730         if (r_maxsurfacelist < model->num_surfaces)
11731         {
11732                 r_maxsurfacelist = model->num_surfaces;
11733                 if (r_surfacelist)
11734                         Mem_Free((msurface_t **)r_surfacelist);
11735                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11736         }
11737
11738         // if the model is static it doesn't matter what value we give for
11739         // wantnormals and wanttangents, so this logic uses only rules applicable
11740         // to a model, knowing that they are meaningless otherwise
11741         if (ent == r_refdef.scene.worldentity)
11742                 RSurf_ActiveWorldEntity();
11743         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11744                 RSurf_ActiveModelEntity(ent, false, false, false);
11745         else if (prepass)
11746                 RSurf_ActiveModelEntity(ent, true, true, true);
11747         else if (depthonly)
11748         {
11749                 switch (vid.renderpath)
11750                 {
11751                 case RENDERPATH_GL20:
11752                 case RENDERPATH_D3D9:
11753                 case RENDERPATH_D3D10:
11754                 case RENDERPATH_D3D11:
11755                 case RENDERPATH_SOFT:
11756                 case RENDERPATH_GLES2:
11757                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11758                         break;
11759                 case RENDERPATH_GL11:
11760                 case RENDERPATH_GL13:
11761                 case RENDERPATH_GLES1:
11762                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11763                         break;
11764                 }
11765         }
11766         else
11767         {
11768                 switch (vid.renderpath)
11769                 {
11770                 case RENDERPATH_GL20:
11771                 case RENDERPATH_D3D9:
11772                 case RENDERPATH_D3D10:
11773                 case RENDERPATH_D3D11:
11774                 case RENDERPATH_SOFT:
11775                 case RENDERPATH_GLES2:
11776                         RSurf_ActiveModelEntity(ent, true, true, false);
11777                         break;
11778                 case RENDERPATH_GL11:
11779                 case RENDERPATH_GL13:
11780                 case RENDERPATH_GLES1:
11781                         RSurf_ActiveModelEntity(ent, true, false, false);
11782                         break;
11783                 }
11784         }
11785
11786         surfaces = model->data_surfaces;
11787         update = model->brushq1.lightmapupdateflags;
11788
11789         // update light styles
11790         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11791         {
11792                 model_brush_lightstyleinfo_t *style;
11793                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11794                 {
11795                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11796                         {
11797                                 int *list = style->surfacelist;
11798                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11799                                 for (j = 0;j < style->numsurfaces;j++)
11800                                         update[list[j]] = true;
11801                         }
11802                 }
11803         }
11804
11805         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11806
11807         if (debug)
11808         {
11809                 R_DrawDebugModel();
11810                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11811                 return;
11812         }
11813
11814         rsurface.lightmaptexture = NULL;
11815         rsurface.deluxemaptexture = NULL;
11816         rsurface.uselightmaptexture = false;
11817         rsurface.texture = NULL;
11818         rsurface.rtlight = NULL;
11819         numsurfacelist = 0;
11820         // add visible surfaces to draw list
11821         for (i = 0;i < model->nummodelsurfaces;i++)
11822                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11823         // don't do anything if there were no surfaces
11824         if (!numsurfacelist)
11825         {
11826                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11827                 return;
11828         }
11829         // update lightmaps if needed
11830         if (update)
11831         {
11832                 int updated = 0;
11833                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11834                 {
11835                         if (update[j])
11836                         {
11837                                 updated++;
11838                                 R_BuildLightMap(ent, surfaces + j);
11839                         }
11840                 }
11841         }
11842
11843         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11844
11845         // add to stats if desired
11846         if (r_speeds.integer && !skysurfaces && !depthonly)
11847         {
11848                 r_refdef.stats.entities_surfaces += numsurfacelist;
11849                 for (j = 0;j < numsurfacelist;j++)
11850                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11851         }
11852
11853         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11854 }
11855
11856 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11857 {
11858         static texture_t texture;
11859         static msurface_t surface;
11860         const msurface_t *surfacelist = &surface;
11861
11862         // fake enough texture and surface state to render this geometry
11863
11864         texture.update_lastrenderframe = -1; // regenerate this texture
11865         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11866         texture.currentskinframe = skinframe;
11867         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11868         texture.offsetmapping = OFFSETMAPPING_OFF;
11869         texture.offsetscale = 1;
11870         texture.specularscalemod = 1;
11871         texture.specularpowermod = 1;
11872
11873         surface.texture = &texture;
11874         surface.num_triangles = numtriangles;
11875         surface.num_firsttriangle = firsttriangle;
11876         surface.num_vertices = numvertices;
11877         surface.num_firstvertex = firstvertex;
11878
11879         // now render it
11880         rsurface.texture = R_GetCurrentTexture(surface.texture);
11881         rsurface.lightmaptexture = NULL;
11882         rsurface.deluxemaptexture = NULL;
11883         rsurface.uselightmaptexture = false;
11884         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11885 }
11886
11887 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)
11888 {
11889         static msurface_t surface;
11890         const msurface_t *surfacelist = &surface;
11891
11892         // fake enough texture and surface state to render this geometry
11893         surface.texture = texture;
11894         surface.num_triangles = numtriangles;
11895         surface.num_firsttriangle = firsttriangle;
11896         surface.num_vertices = numvertices;
11897         surface.num_firstvertex = firstvertex;
11898
11899         // now render it
11900         rsurface.texture = R_GetCurrentTexture(surface.texture);
11901         rsurface.lightmaptexture = NULL;
11902         rsurface.deluxemaptexture = NULL;
11903         rsurface.uselightmaptexture = false;
11904         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11905 }