]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Create a cvar which changes brightness when r_bloom is enabled. This is useful to...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
88 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
91 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
92 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
101 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
125 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
135 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
136 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
137
138 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
139 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
140 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
141 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
142 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
143 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
144 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
145 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
146
147 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
148 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
149
150 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
151 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
152 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
153
154 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
155 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
156 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
157 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
158 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
159 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
160 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
161 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
162 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
163
164 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
165 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
166 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
167 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
168 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
170 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
171 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
172 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
173 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
174 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
175 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
176 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
177 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182
183 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
184 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
185 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
186 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
187 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
188 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
189 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
190 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
191 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
192
193 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
194 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
195 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
196 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
197
198 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
199 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
200
201 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
202 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
203 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
204 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
205 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
206 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
207
208 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
209 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
210 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
211 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
212 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
213 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
214 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
215 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
216 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
217 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
218
219 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
220
221 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
222
223 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
224
225 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
226
227 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
228 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
229
230 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
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         switch (vid.renderpath)
6384         {
6385         case RENDERPATH_GL20:
6386         case RENDERPATH_D3D9:
6387         case RENDERPATH_D3D10:
6388         case RENDERPATH_D3D11:
6389         case RENDERPATH_SOFT:
6390         case RENDERPATH_GLES2:
6391                 permutation =
6392                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6393                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6394                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6395                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6396                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6397
6398                 if (r_fb.colortexture)
6399                 {
6400                         if (!r_fb.fbo)
6401                         {
6402                                 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);
6403                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6404                         }
6405
6406                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6407                         {
6408                                 // declare variables
6409                                 float blur_factor, blur_mouseaccel, blur_velocity;
6410                                 static float blur_average; 
6411                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6412
6413                                 // set a goal for the factoring
6414                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6415                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6416                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6417                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6418                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6419                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6420
6421                                 // from the goal, pick an averaged value between goal and last value
6422                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6423                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6424
6425                                 // enforce minimum amount of blur 
6426                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6427
6428                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6429
6430                                 // calculate values into a standard alpha
6431                                 cl.motionbluralpha = 1 - exp(-
6432                                                 (
6433                                                  (r_motionblur.value * blur_factor / 80)
6434                                                  +
6435                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6436                                                 )
6437                                                 /
6438                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6439                                           );
6440
6441                                 // randomization for the blur value to combat persistent ghosting
6442                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6443                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6444
6445                                 // apply the blur
6446                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6447                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6448                                 {
6449                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6450                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6451                                         switch(vid.renderpath)
6452                                         {
6453                                         case RENDERPATH_GL11:
6454                                         case RENDERPATH_GL13:
6455                                         case RENDERPATH_GL20:
6456                                         case RENDERPATH_GLES1:
6457                                         case RENDERPATH_GLES2:
6458                                         case RENDERPATH_SOFT:
6459                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6460                                                 break;
6461                                         case RENDERPATH_D3D9:
6462                                         case RENDERPATH_D3D10:
6463                                         case RENDERPATH_D3D11:
6464                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6465                                                 break;
6466                                         }
6467                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6468                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6469                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6470                                 }
6471
6472                                 // updates old view angles for next pass
6473                                 VectorCopy(cl.viewangles, blur_oldangles);
6474
6475                                 // copy view into the ghost texture
6476                                 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);
6477                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6478                                 r_fb.ghosttexture_valid = true;
6479                         }
6480                 }
6481                 else
6482                 {
6483                         // no r_fb.colortexture means we're rendering to the real fb
6484                         // we may still have to do view tint...
6485                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6486                         {
6487                                 // apply a color tint to the whole view
6488                                 R_ResetViewRendering2D(0, NULL, NULL);
6489                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6490                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6491                                 R_SetupShader_Generic_NoTexture(false, true);
6492                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6493                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6494                         }
6495                         break; // no screen processing, no bloom, skip it
6496                 }
6497
6498                 if (r_fb.bloomtexture[0])
6499                 {
6500                         // make the bloom texture
6501                         R_Bloom_MakeTexture();
6502                 }
6503
6504 #if _MSC_VER >= 1400
6505 #define sscanf sscanf_s
6506 #endif
6507                 memset(uservecs, 0, sizeof(uservecs));
6508                 if (r_glsl_postprocess_uservec1_enable.integer)
6509                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6510                 if (r_glsl_postprocess_uservec2_enable.integer)
6511                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6512                 if (r_glsl_postprocess_uservec3_enable.integer)
6513                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6514                 if (r_glsl_postprocess_uservec4_enable.integer)
6515                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6516
6517                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6518                 GL_Color(1, 1, 1, 1);
6519                 GL_BlendFunc(GL_ONE, GL_ZERO);
6520
6521                 switch(vid.renderpath)
6522                 {
6523                 case RENDERPATH_GL20:
6524                 case RENDERPATH_GLES2:
6525                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6526                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6527                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6528                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6529                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6530                         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]);
6531                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6532                         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]);
6533                         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]);
6534                         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]);
6535                         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]);
6536                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6537                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6538                         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);
6539                         break;
6540                 case RENDERPATH_D3D9:
6541 #ifdef SUPPORTD3D
6542                         // 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...
6543                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6544                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6545                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6546                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6547                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6548                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6549                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6550                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6551                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6552                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6553                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6554                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6555                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6556                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6557 #endif
6558                         break;
6559                 case RENDERPATH_D3D10:
6560                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6561                         break;
6562                 case RENDERPATH_D3D11:
6563                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6564                         break;
6565                 case RENDERPATH_SOFT:
6566                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6567                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6568                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6569                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6570                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6571                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6572                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6573                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6574                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6577                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6578                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6579                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6580                         break;
6581                 default:
6582                         break;
6583                 }
6584                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6585                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6586                 break;
6587         case RENDERPATH_GL11:
6588         case RENDERPATH_GL13:
6589         case RENDERPATH_GLES1:
6590                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6591                 {
6592                         // apply a color tint to the whole view
6593                         R_ResetViewRendering2D(0, NULL, NULL);
6594                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6595                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6596                         R_SetupShader_Generic_NoTexture(false, true);
6597                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6598                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6599                 }
6600                 break;
6601         }
6602 }
6603
6604 matrix4x4_t r_waterscrollmatrix;
6605
6606 void R_UpdateFog(void)
6607 {
6608         // Nehahra fog
6609         if (gamemode == GAME_NEHAHRA)
6610         {
6611                 if (gl_fogenable.integer)
6612                 {
6613                         r_refdef.oldgl_fogenable = true;
6614                         r_refdef.fog_density = gl_fogdensity.value;
6615                         r_refdef.fog_red = gl_fogred.value;
6616                         r_refdef.fog_green = gl_foggreen.value;
6617                         r_refdef.fog_blue = gl_fogblue.value;
6618                         r_refdef.fog_alpha = 1;
6619                         r_refdef.fog_start = 0;
6620                         r_refdef.fog_end = gl_skyclip.value;
6621                         r_refdef.fog_height = 1<<30;
6622                         r_refdef.fog_fadedepth = 128;
6623                 }
6624                 else if (r_refdef.oldgl_fogenable)
6625                 {
6626                         r_refdef.oldgl_fogenable = false;
6627                         r_refdef.fog_density = 0;
6628                         r_refdef.fog_red = 0;
6629                         r_refdef.fog_green = 0;
6630                         r_refdef.fog_blue = 0;
6631                         r_refdef.fog_alpha = 0;
6632                         r_refdef.fog_start = 0;
6633                         r_refdef.fog_end = 0;
6634                         r_refdef.fog_height = 1<<30;
6635                         r_refdef.fog_fadedepth = 128;
6636                 }
6637         }
6638
6639         // fog parms
6640         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6641         r_refdef.fog_start = max(0, r_refdef.fog_start);
6642         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6643
6644         if (r_refdef.fog_density && r_drawfog.integer)
6645         {
6646                 r_refdef.fogenabled = true;
6647                 // this is the point where the fog reaches 0.9986 alpha, which we
6648                 // consider a good enough cutoff point for the texture
6649                 // (0.9986 * 256 == 255.6)
6650                 if (r_fog_exp2.integer)
6651                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6652                 else
6653                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6654                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6655                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6656                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6657                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6658                         R_BuildFogHeightTexture();
6659                 // fog color was already set
6660                 // update the fog texture
6661                 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)
6662                         R_BuildFogTexture();
6663                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6664                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6665         }
6666         else
6667                 r_refdef.fogenabled = false;
6668
6669         // fog color
6670         if (r_refdef.fog_density)
6671         {
6672                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6673                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6674                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6675
6676                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6677                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6678                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6679                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6680
6681                 {
6682                         vec3_t fogvec;
6683                         VectorCopy(r_refdef.fogcolor, fogvec);
6684                         //   color.rgb *= ContrastBoost * SceneBrightness;
6685                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6686                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6687                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6688                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6689                 }
6690         }
6691 }
6692
6693 void R_UpdateVariables(void)
6694 {
6695         R_Textures_Frame();
6696
6697         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6698
6699         r_refdef.farclip = r_farclip_base.value;
6700         if (r_refdef.scene.worldmodel)
6701                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6702         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6703
6704         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6705                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6706         r_refdef.polygonfactor = 0;
6707         r_refdef.polygonoffset = 0;
6708         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6709         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6710
6711         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6712         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6713         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6714         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6715         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6716         if (FAKELIGHT_ENABLED)
6717         {
6718                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6719         }
6720         else if (r_refdef.scene.worldmodel)
6721         {
6722                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6723         }
6724         if (r_showsurfaces.integer)
6725         {
6726                 r_refdef.scene.rtworld = false;
6727                 r_refdef.scene.rtworldshadows = false;
6728                 r_refdef.scene.rtdlight = false;
6729                 r_refdef.scene.rtdlightshadows = false;
6730                 r_refdef.lightmapintensity = 0;
6731         }
6732
6733         switch(vid.renderpath)
6734         {
6735         case RENDERPATH_GL20:
6736         case RENDERPATH_D3D9:
6737         case RENDERPATH_D3D10:
6738         case RENDERPATH_D3D11:
6739         case RENDERPATH_SOFT:
6740         case RENDERPATH_GLES2:
6741                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6742                 {
6743                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6744                         {
6745                                 // build GLSL gamma texture
6746 #define RAMPWIDTH 256
6747                                 unsigned short ramp[RAMPWIDTH * 3];
6748                                 unsigned char rampbgr[RAMPWIDTH][4];
6749                                 int i;
6750
6751                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6752
6753                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6754                                 for(i = 0; i < RAMPWIDTH; ++i)
6755                                 {
6756                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6757                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6758                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6759                                         rampbgr[i][3] = 0;
6760                                 }
6761                                 if (r_texture_gammaramps)
6762                                 {
6763                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6764                                 }
6765                                 else
6766                                 {
6767                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6768                                 }
6769                         }
6770                 }
6771                 else
6772                 {
6773                         // remove GLSL gamma texture
6774                 }
6775                 break;
6776         case RENDERPATH_GL11:
6777         case RENDERPATH_GL13:
6778         case RENDERPATH_GLES1:
6779                 break;
6780         }
6781 }
6782
6783 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6784 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6785 /*
6786 ================
6787 R_SelectScene
6788 ================
6789 */
6790 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6791         if( scenetype != r_currentscenetype ) {
6792                 // store the old scenetype
6793                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6794                 r_currentscenetype = scenetype;
6795                 // move in the new scene
6796                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6797         }
6798 }
6799
6800 /*
6801 ================
6802 R_GetScenePointer
6803 ================
6804 */
6805 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6806 {
6807         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6808         if( scenetype == r_currentscenetype ) {
6809                 return &r_refdef.scene;
6810         } else {
6811                 return &r_scenes_store[ scenetype ];
6812         }
6813 }
6814
6815 static int R_SortEntities_Compare(const void *ap, const void *bp)
6816 {
6817         const entity_render_t *a = *(const entity_render_t **)ap;
6818         const entity_render_t *b = *(const entity_render_t **)bp;
6819
6820         // 1. compare model
6821         if(a->model < b->model)
6822                 return -1;
6823         if(a->model > b->model)
6824                 return +1;
6825
6826         // 2. compare skin
6827         // TODO possibly calculate the REAL skinnum here first using
6828         // skinscenes?
6829         if(a->skinnum < b->skinnum)
6830                 return -1;
6831         if(a->skinnum > b->skinnum)
6832                 return +1;
6833
6834         // everything we compared is equal
6835         return 0;
6836 }
6837 static void R_SortEntities(void)
6838 {
6839         // below or equal 2 ents, sorting never gains anything
6840         if(r_refdef.scene.numentities <= 2)
6841                 return;
6842         // sort
6843         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6844 }
6845
6846 /*
6847 ================
6848 R_RenderView
6849 ================
6850 */
6851 int dpsoftrast_test;
6852 extern cvar_t r_shadow_bouncegrid;
6853 void R_RenderView(void)
6854 {
6855         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6856         int fbo;
6857         rtexture_t *depthtexture;
6858         rtexture_t *colortexture;
6859
6860         dpsoftrast_test = r_test.integer;
6861
6862         if (r_timereport_active)
6863                 R_TimeReport("start");
6864         r_textureframe++; // used only by R_GetCurrentTexture
6865         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6866
6867         if(R_CompileShader_CheckStaticParms())
6868                 R_GLSL_Restart_f();
6869
6870         if (!r_drawentities.integer)
6871                 r_refdef.scene.numentities = 0;
6872         else if (r_sortentities.integer)
6873                 R_SortEntities();
6874
6875         R_AnimCache_ClearCache();
6876         R_FrameData_NewFrame();
6877
6878         /* adjust for stereo display */
6879         if(R_Stereo_Active())
6880         {
6881                 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);
6882                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6883         }
6884
6885         if (r_refdef.view.isoverlay)
6886         {
6887                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6888                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6889                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6890                 R_TimeReport("depthclear");
6891
6892                 r_refdef.view.showdebug = false;
6893
6894                 r_fb.water.enabled = false;
6895                 r_fb.water.numwaterplanes = 0;
6896
6897                 R_RenderScene(0, NULL, NULL);
6898
6899                 r_refdef.view.matrix = originalmatrix;
6900
6901                 CHECKGLERROR
6902                 return;
6903         }
6904
6905         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6906         {
6907                 r_refdef.view.matrix = originalmatrix;
6908                 return;
6909         }
6910
6911         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6912
6913         // apply bloom brightness offset
6914         if(r_bloom.integer)
6915                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6916
6917         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6918                 // in sRGB fallback, behave similar to true sRGB: convert this
6919                 // value from linear to sRGB
6920                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6921
6922         R_RenderView_UpdateViewVectors();
6923
6924         R_Shadow_UpdateWorldLightSelection();
6925
6926         R_Bloom_StartFrame();
6927         R_Water_StartFrame();
6928
6929         // now we probably have an fbo to render into
6930         fbo = r_fb.fbo;
6931         depthtexture = r_fb.depthtexture;
6932         colortexture = r_fb.colortexture;
6933
6934         CHECKGLERROR
6935         if (r_timereport_active)
6936                 R_TimeReport("viewsetup");
6937
6938         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6939
6940         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6941         {
6942                 R_ClearScreen(r_refdef.fogenabled);
6943                 if (r_timereport_active)
6944                         R_TimeReport("viewclear");
6945         }
6946         r_refdef.view.clear = true;
6947
6948         r_refdef.view.showdebug = true;
6949
6950         R_View_Update();
6951         if (r_timereport_active)
6952                 R_TimeReport("visibility");
6953
6954         R_AnimCache_CacheVisibleEntities();
6955         if (r_timereport_active)
6956                 R_TimeReport("animcache");
6957
6958         R_Shadow_UpdateBounceGridTexture();
6959         if (r_timereport_active && r_shadow_bouncegrid.integer)
6960                 R_TimeReport("bouncegrid");
6961
6962         r_fb.water.numwaterplanes = 0;
6963         if (r_fb.water.enabled)
6964                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6965
6966         R_RenderScene(fbo, depthtexture, colortexture);
6967         r_fb.water.numwaterplanes = 0;
6968
6969         R_BlendView(fbo, depthtexture, colortexture);
6970         if (r_timereport_active)
6971                 R_TimeReport("blendview");
6972
6973         GL_Scissor(0, 0, vid.width, vid.height);
6974         GL_ScissorTest(false);
6975
6976         r_refdef.view.matrix = originalmatrix;
6977
6978         CHECKGLERROR
6979 }
6980
6981 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6982 {
6983         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6984         {
6985                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6986                 if (r_timereport_active)
6987                         R_TimeReport("waterworld");
6988         }
6989
6990         // don't let sound skip if going slow
6991         if (r_refdef.scene.extraupdate)
6992                 S_ExtraUpdate ();
6993
6994         R_DrawModelsAddWaterPlanes();
6995         if (r_timereport_active)
6996                 R_TimeReport("watermodels");
6997
6998         if (r_fb.water.numwaterplanes)
6999         {
7000                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7001                 if (r_timereport_active)
7002                         R_TimeReport("waterscenes");
7003         }
7004 }
7005
7006 extern cvar_t cl_locs_show;
7007 static void R_DrawLocs(void);
7008 static void R_DrawEntityBBoxes(void);
7009 static void R_DrawModelDecals(void);
7010 extern cvar_t cl_decals_newsystem;
7011 extern qboolean r_shadow_usingdeferredprepass;
7012 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7013 {
7014         qboolean shadowmapping = false;
7015
7016         if (r_timereport_active)
7017                 R_TimeReport("beginscene");
7018
7019         r_refdef.stats.renders++;
7020
7021         R_UpdateFog();
7022
7023         // don't let sound skip if going slow
7024         if (r_refdef.scene.extraupdate)
7025                 S_ExtraUpdate ();
7026
7027         R_MeshQueue_BeginScene();
7028
7029         R_SkyStartFrame();
7030
7031         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);
7032
7033         if (r_timereport_active)
7034                 R_TimeReport("skystartframe");
7035
7036         if (cl.csqc_vidvars.drawworld)
7037         {
7038                 // don't let sound skip if going slow
7039                 if (r_refdef.scene.extraupdate)
7040                         S_ExtraUpdate ();
7041
7042                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7043                 {
7044                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7045                         if (r_timereport_active)
7046                                 R_TimeReport("worldsky");
7047                 }
7048
7049                 if (R_DrawBrushModelsSky() && r_timereport_active)
7050                         R_TimeReport("bmodelsky");
7051
7052                 if (skyrendermasked && skyrenderlater)
7053                 {
7054                         // we have to force off the water clipping plane while rendering sky
7055                         R_SetupView(false, fbo, depthtexture, colortexture);
7056                         R_Sky();
7057                         R_SetupView(true, fbo, depthtexture, colortexture);
7058                         if (r_timereport_active)
7059                                 R_TimeReport("sky");
7060                 }
7061         }
7062
7063         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7064         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7065                 R_Shadow_PrepareModelShadows();
7066         if (r_timereport_active)
7067                 R_TimeReport("preparelights");
7068
7069         if (R_Shadow_ShadowMappingEnabled())
7070                 shadowmapping = true;
7071
7072         if (r_shadow_usingdeferredprepass)
7073                 R_Shadow_DrawPrepass();
7074
7075         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7076         {
7077                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7078                 if (r_timereport_active)
7079                         R_TimeReport("worlddepth");
7080         }
7081         if (r_depthfirst.integer >= 2)
7082         {
7083                 R_DrawModelsDepth();
7084                 if (r_timereport_active)
7085                         R_TimeReport("modeldepth");
7086         }
7087
7088         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7089         {
7090                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7091                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7092                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7093                 // don't let sound skip if going slow
7094                 if (r_refdef.scene.extraupdate)
7095                         S_ExtraUpdate ();
7096         }
7097
7098         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7099         {
7100                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7101                 if (r_timereport_active)
7102                         R_TimeReport("world");
7103         }
7104
7105         // don't let sound skip if going slow
7106         if (r_refdef.scene.extraupdate)
7107                 S_ExtraUpdate ();
7108
7109         R_DrawModels();
7110         if (r_timereport_active)
7111                 R_TimeReport("models");
7112
7113         // don't let sound skip if going slow
7114         if (r_refdef.scene.extraupdate)
7115                 S_ExtraUpdate ();
7116
7117         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7118         {
7119                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7120                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7121                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7122                 // don't let sound skip if going slow
7123                 if (r_refdef.scene.extraupdate)
7124                         S_ExtraUpdate ();
7125         }
7126
7127         if (!r_shadow_usingdeferredprepass)
7128         {
7129                 R_Shadow_DrawLights();
7130                 if (r_timereport_active)
7131                         R_TimeReport("rtlights");
7132         }
7133
7134         // don't let sound skip if going slow
7135         if (r_refdef.scene.extraupdate)
7136                 S_ExtraUpdate ();
7137
7138         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7139         {
7140                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7141                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7142                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7143                 // don't let sound skip if going slow
7144                 if (r_refdef.scene.extraupdate)
7145                         S_ExtraUpdate ();
7146         }
7147
7148         if (cl.csqc_vidvars.drawworld)
7149         {
7150                 if (cl_decals_newsystem.integer)
7151                 {
7152                         R_DrawModelDecals();
7153                         if (r_timereport_active)
7154                                 R_TimeReport("modeldecals");
7155                 }
7156                 else
7157                 {
7158                         R_DrawDecals();
7159                         if (r_timereport_active)
7160                                 R_TimeReport("decals");
7161                 }
7162
7163                 R_DrawParticles();
7164                 if (r_timereport_active)
7165                         R_TimeReport("particles");
7166
7167                 R_DrawExplosions();
7168                 if (r_timereport_active)
7169                         R_TimeReport("explosions");
7170
7171                 R_DrawLightningBeams();
7172                 if (r_timereport_active)
7173                         R_TimeReport("lightning");
7174         }
7175
7176         if (cl.csqc_loaded)
7177                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7178
7179         if (r_refdef.view.showdebug)
7180         {
7181                 if (cl_locs_show.integer)
7182                 {
7183                         R_DrawLocs();
7184                         if (r_timereport_active)
7185                                 R_TimeReport("showlocs");
7186                 }
7187
7188                 if (r_drawportals.integer)
7189                 {
7190                         R_DrawPortals();
7191                         if (r_timereport_active)
7192                                 R_TimeReport("portals");
7193                 }
7194
7195                 if (r_showbboxes.value > 0)
7196                 {
7197                         R_DrawEntityBBoxes();
7198                         if (r_timereport_active)
7199                                 R_TimeReport("bboxes");
7200                 }
7201         }
7202
7203         if (r_transparent.integer)
7204         {
7205                 R_MeshQueue_RenderTransparent();
7206                 if (r_timereport_active)
7207                         R_TimeReport("drawtrans");
7208         }
7209
7210         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))
7211         {
7212                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7213                 if (r_timereport_active)
7214                         R_TimeReport("worlddebug");
7215                 R_DrawModelsDebug();
7216                 if (r_timereport_active)
7217                         R_TimeReport("modeldebug");
7218         }
7219
7220         if (cl.csqc_vidvars.drawworld)
7221         {
7222                 R_Shadow_DrawCoronas();
7223                 if (r_timereport_active)
7224                         R_TimeReport("coronas");
7225         }
7226
7227 #if 0
7228         {
7229                 GL_DepthTest(false);
7230                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7231                 GL_Color(1, 1, 1, 1);
7232                 qglBegin(GL_POLYGON);
7233                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7234                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7235                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7236                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7237                 qglEnd();
7238                 qglBegin(GL_POLYGON);
7239                 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]);
7240                 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]);
7241                 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]);
7242                 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]);
7243                 qglEnd();
7244                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7245         }
7246 #endif
7247
7248         // don't let sound skip if going slow
7249         if (r_refdef.scene.extraupdate)
7250                 S_ExtraUpdate ();
7251 }
7252
7253 static const unsigned short bboxelements[36] =
7254 {
7255         5, 1, 3, 5, 3, 7,
7256         6, 2, 0, 6, 0, 4,
7257         7, 3, 2, 7, 2, 6,
7258         4, 0, 1, 4, 1, 5,
7259         4, 5, 7, 4, 7, 6,
7260         1, 0, 2, 1, 2, 3,
7261 };
7262
7263 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7264 {
7265         int i;
7266         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7267
7268         RSurf_ActiveWorldEntity();
7269
7270         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7271         GL_DepthMask(false);
7272         GL_DepthRange(0, 1);
7273         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7274 //      R_Mesh_ResetTextureState();
7275
7276         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7277         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7278         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7279         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7280         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7281         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7282         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7283         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7284         R_FillColors(color4f, 8, cr, cg, cb, ca);
7285         if (r_refdef.fogenabled)
7286         {
7287                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7288                 {
7289                         f1 = RSurf_FogVertex(v);
7290                         f2 = 1 - f1;
7291                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7292                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7293                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7294                 }
7295         }
7296         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7297         R_Mesh_ResetTextureState();
7298         R_SetupShader_Generic_NoTexture(false, false);
7299         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7300 }
7301
7302 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7303 {
7304         prvm_prog_t *prog = SVVM_prog;
7305         int i;
7306         float color[4];
7307         prvm_edict_t *edict;
7308
7309         // this function draws bounding boxes of server entities
7310         if (!sv.active)
7311                 return;
7312
7313         GL_CullFace(GL_NONE);
7314         R_SetupShader_Generic_NoTexture(false, false);
7315
7316         for (i = 0;i < numsurfaces;i++)
7317         {
7318                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7319                 switch ((int)PRVM_serveredictfloat(edict, solid))
7320                 {
7321                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7322                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7323                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7324                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7325                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7326                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7327                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7328                 }
7329                 color[3] *= r_showbboxes.value;
7330                 color[3] = bound(0, color[3], 1);
7331                 GL_DepthTest(!r_showdisabledepthtest.integer);
7332                 GL_CullFace(r_refdef.view.cullface_front);
7333                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7334         }
7335 }
7336
7337 static void R_DrawEntityBBoxes(void)
7338 {
7339         int i;
7340         prvm_edict_t *edict;
7341         vec3_t center;
7342         prvm_prog_t *prog = SVVM_prog;
7343
7344         // this function draws bounding boxes of server entities
7345         if (!sv.active)
7346                 return;
7347
7348         for (i = 0;i < prog->num_edicts;i++)
7349         {
7350                 edict = PRVM_EDICT_NUM(i);
7351                 if (edict->priv.server->free)
7352                         continue;
7353                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7354                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7355                         continue;
7356                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7357                         continue;
7358                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7359                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7360         }
7361 }
7362
7363 static const int nomodelelement3i[24] =
7364 {
7365         5, 2, 0,
7366         5, 1, 2,
7367         5, 0, 3,
7368         5, 3, 1,
7369         0, 2, 4,
7370         2, 1, 4,
7371         3, 0, 4,
7372         1, 3, 4
7373 };
7374
7375 static const unsigned short nomodelelement3s[24] =
7376 {
7377         5, 2, 0,
7378         5, 1, 2,
7379         5, 0, 3,
7380         5, 3, 1,
7381         0, 2, 4,
7382         2, 1, 4,
7383         3, 0, 4,
7384         1, 3, 4
7385 };
7386
7387 static const float nomodelvertex3f[6*3] =
7388 {
7389         -16,   0,   0,
7390          16,   0,   0,
7391           0, -16,   0,
7392           0,  16,   0,
7393           0,   0, -16,
7394           0,   0,  16
7395 };
7396
7397 static const float nomodelcolor4f[6*4] =
7398 {
7399         0.0f, 0.0f, 0.5f, 1.0f,
7400         0.0f, 0.0f, 0.5f, 1.0f,
7401         0.0f, 0.5f, 0.0f, 1.0f,
7402         0.0f, 0.5f, 0.0f, 1.0f,
7403         0.5f, 0.0f, 0.0f, 1.0f,
7404         0.5f, 0.0f, 0.0f, 1.0f
7405 };
7406
7407 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7408 {
7409         int i;
7410         float f1, f2, *c;
7411         float color4f[6*4];
7412
7413         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);
7414
7415         // this is only called once per entity so numsurfaces is always 1, and
7416         // surfacelist is always {0}, so this code does not handle batches
7417
7418         if (rsurface.ent_flags & RENDER_ADDITIVE)
7419         {
7420                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7421                 GL_DepthMask(false);
7422         }
7423         else if (rsurface.colormod[3] < 1)
7424         {
7425                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7426                 GL_DepthMask(false);
7427         }
7428         else
7429         {
7430                 GL_BlendFunc(GL_ONE, GL_ZERO);
7431                 GL_DepthMask(true);
7432         }
7433         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7434         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7435         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7436         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7437         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7438         for (i = 0, c = color4f;i < 6;i++, c += 4)
7439         {
7440                 c[0] *= rsurface.colormod[0];
7441                 c[1] *= rsurface.colormod[1];
7442                 c[2] *= rsurface.colormod[2];
7443                 c[3] *= rsurface.colormod[3];
7444         }
7445         if (r_refdef.fogenabled)
7446         {
7447                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7448                 {
7449                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7450                         f2 = 1 - f1;
7451                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7452                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7453                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7454                 }
7455         }
7456 //      R_Mesh_ResetTextureState();
7457         R_SetupShader_Generic_NoTexture(false, false);
7458         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7459         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7460 }
7461
7462 void R_DrawNoModel(entity_render_t *ent)
7463 {
7464         vec3_t org;
7465         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7466         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7467                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7468         else
7469                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7470 }
7471
7472 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7473 {
7474         vec3_t right1, right2, diff, normal;
7475
7476         VectorSubtract (org2, org1, normal);
7477
7478         // calculate 'right' vector for start
7479         VectorSubtract (r_refdef.view.origin, org1, diff);
7480         CrossProduct (normal, diff, right1);
7481         VectorNormalize (right1);
7482
7483         // calculate 'right' vector for end
7484         VectorSubtract (r_refdef.view.origin, org2, diff);
7485         CrossProduct (normal, diff, right2);
7486         VectorNormalize (right2);
7487
7488         vert[ 0] = org1[0] + width * right1[0];
7489         vert[ 1] = org1[1] + width * right1[1];
7490         vert[ 2] = org1[2] + width * right1[2];
7491         vert[ 3] = org1[0] - width * right1[0];
7492         vert[ 4] = org1[1] - width * right1[1];
7493         vert[ 5] = org1[2] - width * right1[2];
7494         vert[ 6] = org2[0] - width * right2[0];
7495         vert[ 7] = org2[1] - width * right2[1];
7496         vert[ 8] = org2[2] - width * right2[2];
7497         vert[ 9] = org2[0] + width * right2[0];
7498         vert[10] = org2[1] + width * right2[1];
7499         vert[11] = org2[2] + width * right2[2];
7500 }
7501
7502 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)
7503 {
7504         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7505         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7506         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7507         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7508         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7509         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7510         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7511         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7512         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7513         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7514         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7515         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7516 }
7517
7518 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7519 {
7520         int i;
7521         float *vertex3f;
7522         float v[3];
7523         VectorSet(v, x, y, z);
7524         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7525                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7526                         break;
7527         if (i == mesh->numvertices)
7528         {
7529                 if (mesh->numvertices < mesh->maxvertices)
7530                 {
7531                         VectorCopy(v, vertex3f);
7532                         mesh->numvertices++;
7533                 }
7534                 return mesh->numvertices;
7535         }
7536         else
7537                 return i;
7538 }
7539
7540 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7541 {
7542         int i;
7543         int *e, element[3];
7544         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7545         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7546         e = mesh->element3i + mesh->numtriangles * 3;
7547         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7548         {
7549                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7550                 if (mesh->numtriangles < mesh->maxtriangles)
7551                 {
7552                         *e++ = element[0];
7553                         *e++ = element[1];
7554                         *e++ = element[2];
7555                         mesh->numtriangles++;
7556                 }
7557                 element[1] = element[2];
7558         }
7559 }
7560
7561 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7562 {
7563         int i;
7564         int *e, element[3];
7565         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7566         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7567         e = mesh->element3i + mesh->numtriangles * 3;
7568         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7569         {
7570                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7571                 if (mesh->numtriangles < mesh->maxtriangles)
7572                 {
7573                         *e++ = element[0];
7574                         *e++ = element[1];
7575                         *e++ = element[2];
7576                         mesh->numtriangles++;
7577                 }
7578                 element[1] = element[2];
7579         }
7580 }
7581
7582 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7583 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7584 {
7585         int planenum, planenum2;
7586         int w;
7587         int tempnumpoints;
7588         mplane_t *plane, *plane2;
7589         double maxdist;
7590         double temppoints[2][256*3];
7591         // figure out how large a bounding box we need to properly compute this brush
7592         maxdist = 0;
7593         for (w = 0;w < numplanes;w++)
7594                 maxdist = max(maxdist, fabs(planes[w].dist));
7595         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7596         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7597         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7598         {
7599                 w = 0;
7600                 tempnumpoints = 4;
7601                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7602                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7603                 {
7604                         if (planenum2 == planenum)
7605                                 continue;
7606                         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);
7607                         w = !w;
7608                 }
7609                 if (tempnumpoints < 3)
7610                         continue;
7611                 // generate elements forming a triangle fan for this polygon
7612                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7613         }
7614 }
7615
7616 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)
7617 {
7618         texturelayer_t *layer;
7619         layer = t->currentlayers + t->currentnumlayers++;
7620         layer->type = type;
7621         layer->depthmask = depthmask;
7622         layer->blendfunc1 = blendfunc1;
7623         layer->blendfunc2 = blendfunc2;
7624         layer->texture = texture;
7625         layer->texmatrix = *matrix;
7626         layer->color[0] = r;
7627         layer->color[1] = g;
7628         layer->color[2] = b;
7629         layer->color[3] = a;
7630 }
7631
7632 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7633 {
7634         if(parms[0] == 0 && parms[1] == 0)
7635                 return false;
7636         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7637                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7638                         return false;
7639         return true;
7640 }
7641
7642 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7643 {
7644         double index, f;
7645         index = parms[2] + rsurface.shadertime * parms[3];
7646         index -= floor(index);
7647         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7648         {
7649         default:
7650         case Q3WAVEFUNC_NONE:
7651         case Q3WAVEFUNC_NOISE:
7652         case Q3WAVEFUNC_COUNT:
7653                 f = 0;
7654                 break;
7655         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7656         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7657         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7658         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7659         case Q3WAVEFUNC_TRIANGLE:
7660                 index *= 4;
7661                 f = index - floor(index);
7662                 if (index < 1)
7663                 {
7664                         // f = f;
7665                 }
7666                 else if (index < 2)
7667                         f = 1 - f;
7668                 else if (index < 3)
7669                         f = -f;
7670                 else
7671                         f = -(1 - f);
7672                 break;
7673         }
7674         f = parms[0] + parms[1] * f;
7675         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7676                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7677         return (float) f;
7678 }
7679
7680 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7681 {
7682         int w, h, idx;
7683         double f;
7684         double offsetd[2];
7685         float tcmat[12];
7686         matrix4x4_t matrix, temp;
7687         switch(tcmod->tcmod)
7688         {
7689                 case Q3TCMOD_COUNT:
7690                 case Q3TCMOD_NONE:
7691                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7692                                 matrix = r_waterscrollmatrix;
7693                         else
7694                                 matrix = identitymatrix;
7695                         break;
7696                 case Q3TCMOD_ENTITYTRANSLATE:
7697                         // this is used in Q3 to allow the gamecode to control texcoord
7698                         // scrolling on the entity, which is not supported in darkplaces yet.
7699                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7700                         break;
7701                 case Q3TCMOD_ROTATE:
7702                         f = tcmod->parms[0] * rsurface.shadertime;
7703                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7704                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7705                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7706                         break;
7707                 case Q3TCMOD_SCALE:
7708                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7709                         break;
7710                 case Q3TCMOD_SCROLL:
7711                         // extra care is needed because of precision breakdown with large values of time
7712                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7713                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7714                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7715                         break;
7716                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7717                         w = (int) tcmod->parms[0];
7718                         h = (int) tcmod->parms[1];
7719                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7720                         f = f - floor(f);
7721                         idx = (int) floor(f * w * h);
7722                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7723                         break;
7724                 case Q3TCMOD_STRETCH:
7725                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7726                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7727                         break;
7728                 case Q3TCMOD_TRANSFORM:
7729                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7730                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7731                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7732                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7733                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7734                         break;
7735                 case Q3TCMOD_TURBULENT:
7736                         // this is handled in the RSurf_PrepareVertices function
7737                         matrix = identitymatrix;
7738                         break;
7739         }
7740         temp = *texmatrix;
7741         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7742 }
7743
7744 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7745 {
7746         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7747         char name[MAX_QPATH];
7748         skinframe_t *skinframe;
7749         unsigned char pixels[296*194];
7750         strlcpy(cache->name, skinname, sizeof(cache->name));
7751         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7752         if (developer_loading.integer)
7753                 Con_Printf("loading %s\n", name);
7754         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7755         if (!skinframe || !skinframe->base)
7756         {
7757                 unsigned char *f;
7758                 fs_offset_t filesize;
7759                 skinframe = NULL;
7760                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7761                 if (f)
7762                 {
7763                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7764                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7765                         Mem_Free(f);
7766                 }
7767         }
7768         cache->skinframe = skinframe;
7769 }
7770
7771 texture_t *R_GetCurrentTexture(texture_t *t)
7772 {
7773         int i;
7774         const entity_render_t *ent = rsurface.entity;
7775         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7776         q3shaderinfo_layer_tcmod_t *tcmod;
7777
7778         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7779                 return t->currentframe;
7780         t->update_lastrenderframe = r_textureframe;
7781         t->update_lastrenderentity = (void *)ent;
7782
7783         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7784                 t->camera_entity = ent->entitynumber;
7785         else
7786                 t->camera_entity = 0;
7787
7788         // switch to an alternate material if this is a q1bsp animated material
7789         {
7790                 texture_t *texture = t;
7791                 int s = rsurface.ent_skinnum;
7792                 if ((unsigned int)s >= (unsigned int)model->numskins)
7793                         s = 0;
7794                 if (model->skinscenes)
7795                 {
7796                         if (model->skinscenes[s].framecount > 1)
7797                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7798                         else
7799                                 s = model->skinscenes[s].firstframe;
7800                 }
7801                 if (s > 0)
7802                         t = t + s * model->num_surfaces;
7803                 if (t->animated)
7804                 {
7805                         // use an alternate animation if the entity's frame is not 0,
7806                         // and only if the texture has an alternate animation
7807                         if (rsurface.ent_alttextures && t->anim_total[1])
7808                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7809                         else
7810                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7811                 }
7812                 texture->currentframe = t;
7813         }
7814
7815         // update currentskinframe to be a qw skin or animation frame
7816         if (rsurface.ent_qwskin >= 0)
7817         {
7818                 i = rsurface.ent_qwskin;
7819                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7820                 {
7821                         r_qwskincache_size = cl.maxclients;
7822                         if (r_qwskincache)
7823                                 Mem_Free(r_qwskincache);
7824                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7825                 }
7826                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7827                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7828                 t->currentskinframe = r_qwskincache[i].skinframe;
7829                 if (t->currentskinframe == NULL)
7830                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7831         }
7832         else if (t->numskinframes >= 2)
7833                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7834         if (t->backgroundnumskinframes >= 2)
7835                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7836
7837         t->currentmaterialflags = t->basematerialflags;
7838         t->currentalpha = rsurface.colormod[3];
7839         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7840                 t->currentalpha *= r_wateralpha.value;
7841         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7842                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7843         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7844                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7845         if (!(rsurface.ent_flags & RENDER_LIGHT))
7846                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7847         else if (FAKELIGHT_ENABLED)
7848         {
7849                 // no modellight if using fakelight for the map
7850         }
7851         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7852         {
7853                 // pick a model lighting mode
7854                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7855                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7856                 else
7857                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7858         }
7859         if (rsurface.ent_flags & RENDER_ADDITIVE)
7860                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7861         else if (t->currentalpha < 1)
7862                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7863         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7864         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7865                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7866         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7867                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7868         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7869                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7870         if (t->backgroundnumskinframes)
7871                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7872         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7873         {
7874                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7875                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7876         }
7877         else
7878                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7879         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7880         {
7881                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7882                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7883         }
7884         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7885                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7886
7887         // there is no tcmod
7888         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7889         {
7890                 t->currenttexmatrix = r_waterscrollmatrix;
7891                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7892         }
7893         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7894         {
7895                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7896                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7897         }
7898
7899         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7900                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7901         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7902                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7903
7904         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7905         if (t->currentskinframe->qpixels)
7906                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7907         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7908         if (!t->basetexture)
7909                 t->basetexture = r_texture_notexture;
7910         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7911         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7912         t->nmaptexture = t->currentskinframe->nmap;
7913         if (!t->nmaptexture)
7914                 t->nmaptexture = r_texture_blanknormalmap;
7915         t->glosstexture = r_texture_black;
7916         t->glowtexture = t->currentskinframe->glow;
7917         t->fogtexture = t->currentskinframe->fog;
7918         t->reflectmasktexture = t->currentskinframe->reflect;
7919         if (t->backgroundnumskinframes)
7920         {
7921                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7922                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7923                 t->backgroundglosstexture = r_texture_black;
7924                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7925                 if (!t->backgroundnmaptexture)
7926                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7927                 // make sure that if glow is going to be used, both textures are not NULL
7928                 if (!t->backgroundglowtexture && t->glowtexture)
7929                         t->backgroundglowtexture = r_texture_black;
7930                 if (!t->glowtexture && t->backgroundglowtexture)
7931                         t->glowtexture = r_texture_black;
7932         }
7933         else
7934         {
7935                 t->backgroundbasetexture = r_texture_white;
7936                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7937                 t->backgroundglosstexture = r_texture_black;
7938                 t->backgroundglowtexture = NULL;
7939         }
7940         t->specularpower = r_shadow_glossexponent.value;
7941         // TODO: store reference values for these in the texture?
7942         t->specularscale = 0;
7943         if (r_shadow_gloss.integer > 0)
7944         {
7945                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7946                 {
7947                         if (r_shadow_glossintensity.value > 0)
7948                         {
7949                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7950                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7951                                 t->specularscale = r_shadow_glossintensity.value;
7952                         }
7953                 }
7954                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7955                 {
7956                         t->glosstexture = r_texture_white;
7957                         t->backgroundglosstexture = r_texture_white;
7958                         t->specularscale = r_shadow_gloss2intensity.value;
7959                         t->specularpower = r_shadow_gloss2exponent.value;
7960                 }
7961         }
7962         t->specularscale *= t->specularscalemod;
7963         t->specularpower *= t->specularpowermod;
7964         t->rtlightambient = 0;
7965
7966         // lightmaps mode looks bad with dlights using actual texturing, so turn
7967         // off the colormap and glossmap, but leave the normalmap on as it still
7968         // accurately represents the shading involved
7969         if (gl_lightmaps.integer)
7970         {
7971                 t->basetexture = r_texture_grey128;
7972                 t->pantstexture = r_texture_black;
7973                 t->shirttexture = r_texture_black;
7974                 t->nmaptexture = r_texture_blanknormalmap;
7975                 t->glosstexture = r_texture_black;
7976                 t->glowtexture = NULL;
7977                 t->fogtexture = NULL;
7978                 t->reflectmasktexture = NULL;
7979                 t->backgroundbasetexture = NULL;
7980                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7981                 t->backgroundglosstexture = r_texture_black;
7982                 t->backgroundglowtexture = NULL;
7983                 t->specularscale = 0;
7984                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7985         }
7986
7987         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7988         VectorClear(t->dlightcolor);
7989         t->currentnumlayers = 0;
7990         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7991         {
7992                 int blendfunc1, blendfunc2;
7993                 qboolean depthmask;
7994                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7995                 {
7996                         blendfunc1 = GL_SRC_ALPHA;
7997                         blendfunc2 = GL_ONE;
7998                 }
7999                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8000                 {
8001                         blendfunc1 = GL_SRC_ALPHA;
8002                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8003                 }
8004                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8005                 {
8006                         blendfunc1 = t->customblendfunc[0];
8007                         blendfunc2 = t->customblendfunc[1];
8008                 }
8009                 else
8010                 {
8011                         blendfunc1 = GL_ONE;
8012                         blendfunc2 = GL_ZERO;
8013                 }
8014                 // don't colormod evilblend textures
8015                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8016                         VectorSet(t->lightmapcolor, 1, 1, 1);
8017                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8018                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8019                 {
8020                         // fullbright is not affected by r_refdef.lightmapintensity
8021                         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]);
8022                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8023                                 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]);
8024                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8025                                 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]);
8026                 }
8027                 else
8028                 {
8029                         vec3_t ambientcolor;
8030                         float colorscale;
8031                         // set the color tint used for lights affecting this surface
8032                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8033                         colorscale = 2;
8034                         // q3bsp has no lightmap updates, so the lightstylevalue that
8035                         // would normally be baked into the lightmap must be
8036                         // applied to the color
8037                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8038                         if (model->type == mod_brushq3)
8039                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8040                         colorscale *= r_refdef.lightmapintensity;
8041                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8042                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8043                         // basic lit geometry
8044                         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]);
8045                         // add pants/shirt if needed
8046                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8047                                 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]);
8048                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8049                                 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]);
8050                         // now add ambient passes if needed
8051                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8052                         {
8053                                 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]);
8054                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8055                                         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]);
8056                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8057                                         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]);
8058                         }
8059                 }
8060                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8061                         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]);
8062                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8063                 {
8064                         // if this is opaque use alpha blend which will darken the earlier
8065                         // passes cheaply.
8066                         //
8067                         // if this is an alpha blended material, all the earlier passes
8068                         // were darkened by fog already, so we only need to add the fog
8069                         // color ontop through the fog mask texture
8070                         //
8071                         // if this is an additive blended material, all the earlier passes
8072                         // were darkened by fog already, and we should not add fog color
8073                         // (because the background was not darkened, there is no fog color
8074                         // that was lost behind it).
8075                         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]);
8076                 }
8077         }
8078
8079         return t->currentframe;
8080 }
8081
8082 rsurfacestate_t rsurface;
8083
8084 void RSurf_ActiveWorldEntity(void)
8085 {
8086         dp_model_t *model = r_refdef.scene.worldmodel;
8087         //if (rsurface.entity == r_refdef.scene.worldentity)
8088         //      return;
8089         rsurface.entity = r_refdef.scene.worldentity;
8090         rsurface.skeleton = NULL;
8091         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8092         rsurface.ent_skinnum = 0;
8093         rsurface.ent_qwskin = -1;
8094         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8095         rsurface.shadertime = r_refdef.scene.time;
8096         rsurface.matrix = identitymatrix;
8097         rsurface.inversematrix = identitymatrix;
8098         rsurface.matrixscale = 1;
8099         rsurface.inversematrixscale = 1;
8100         R_EntityMatrix(&identitymatrix);
8101         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8102         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8103         rsurface.fograngerecip = r_refdef.fograngerecip;
8104         rsurface.fogheightfade = r_refdef.fogheightfade;
8105         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8106         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8107         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8108         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8109         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8110         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8111         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8112         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8113         rsurface.colormod[3] = 1;
8114         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);
8115         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8116         rsurface.frameblend[0].lerp = 1;
8117         rsurface.ent_alttextures = false;
8118         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8119         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8120         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8121         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8122         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8123         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8124         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8126         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8127         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8129         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8130         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8131         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8132         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8133         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8134         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8135         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8136         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8137         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8138         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8139         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8141         rsurface.modelelement3i = model->surfmesh.data_element3i;
8142         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8143         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8144         rsurface.modelelement3s = model->surfmesh.data_element3s;
8145         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8146         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8147         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8148         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8149         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8150         rsurface.modelsurfaces = model->data_surfaces;
8151         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8152         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8153         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8154         rsurface.modelgeneratedvertex = false;
8155         rsurface.batchgeneratedvertex = false;
8156         rsurface.batchfirstvertex = 0;
8157         rsurface.batchnumvertices = 0;
8158         rsurface.batchfirsttriangle = 0;
8159         rsurface.batchnumtriangles = 0;
8160         rsurface.batchvertex3f  = NULL;
8161         rsurface.batchvertex3f_vertexbuffer = NULL;
8162         rsurface.batchvertex3f_bufferoffset = 0;
8163         rsurface.batchsvector3f = NULL;
8164         rsurface.batchsvector3f_vertexbuffer = NULL;
8165         rsurface.batchsvector3f_bufferoffset = 0;
8166         rsurface.batchtvector3f = NULL;
8167         rsurface.batchtvector3f_vertexbuffer = NULL;
8168         rsurface.batchtvector3f_bufferoffset = 0;
8169         rsurface.batchnormal3f  = NULL;
8170         rsurface.batchnormal3f_vertexbuffer = NULL;
8171         rsurface.batchnormal3f_bufferoffset = 0;
8172         rsurface.batchlightmapcolor4f = NULL;
8173         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8174         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8175         rsurface.batchtexcoordtexture2f = NULL;
8176         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8177         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8178         rsurface.batchtexcoordlightmap2f = NULL;
8179         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8180         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8181         rsurface.batchvertexmesh = NULL;
8182         rsurface.batchvertexmeshbuffer = NULL;
8183         rsurface.batchvertex3fbuffer = NULL;
8184         rsurface.batchelement3i = NULL;
8185         rsurface.batchelement3i_indexbuffer = NULL;
8186         rsurface.batchelement3i_bufferoffset = 0;
8187         rsurface.batchelement3s = NULL;
8188         rsurface.batchelement3s_indexbuffer = NULL;
8189         rsurface.batchelement3s_bufferoffset = 0;
8190         rsurface.passcolor4f = NULL;
8191         rsurface.passcolor4f_vertexbuffer = NULL;
8192         rsurface.passcolor4f_bufferoffset = 0;
8193         rsurface.forcecurrenttextureupdate = false;
8194 }
8195
8196 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8197 {
8198         dp_model_t *model = ent->model;
8199         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8200         //      return;
8201         rsurface.entity = (entity_render_t *)ent;
8202         rsurface.skeleton = ent->skeleton;
8203         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8204         rsurface.ent_skinnum = ent->skinnum;
8205         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;
8206         rsurface.ent_flags = ent->flags;
8207         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8208         rsurface.matrix = ent->matrix;
8209         rsurface.inversematrix = ent->inversematrix;
8210         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8211         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8212         R_EntityMatrix(&rsurface.matrix);
8213         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8214         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8215         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8216         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8217         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8218         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8219         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8220         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8221         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8222         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8223         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8224         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8225         rsurface.colormod[3] = ent->alpha;
8226         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8227         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8228         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8229         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8230         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8231         if (ent->model->brush.submodel && !prepass)
8232         {
8233                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8234                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8235         }
8236         if (model->surfmesh.isanimated && model->AnimateVertices)
8237         {
8238                 if (ent->animcache_vertex3f)
8239                 {
8240                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8241                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8242                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8243                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8244                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8245                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8246                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8247                 }
8248                 else if (wanttangents)
8249                 {
8250                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8251                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8252                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8253                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8254                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8255                         rsurface.modelvertexmesh = NULL;
8256                         rsurface.modelvertexmeshbuffer = NULL;
8257                         rsurface.modelvertex3fbuffer = NULL;
8258                 }
8259                 else if (wantnormals)
8260                 {
8261                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8262                         rsurface.modelsvector3f = NULL;
8263                         rsurface.modeltvector3f = NULL;
8264                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8265                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8266                         rsurface.modelvertexmesh = NULL;
8267                         rsurface.modelvertexmeshbuffer = NULL;
8268                         rsurface.modelvertex3fbuffer = NULL;
8269                 }
8270                 else
8271                 {
8272                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8273                         rsurface.modelsvector3f = NULL;
8274                         rsurface.modeltvector3f = NULL;
8275                         rsurface.modelnormal3f = NULL;
8276                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8277                         rsurface.modelvertexmesh = NULL;
8278                         rsurface.modelvertexmeshbuffer = NULL;
8279                         rsurface.modelvertex3fbuffer = NULL;
8280                 }
8281                 rsurface.modelvertex3f_vertexbuffer = 0;
8282                 rsurface.modelvertex3f_bufferoffset = 0;
8283                 rsurface.modelsvector3f_vertexbuffer = 0;
8284                 rsurface.modelsvector3f_bufferoffset = 0;
8285                 rsurface.modeltvector3f_vertexbuffer = 0;
8286                 rsurface.modeltvector3f_bufferoffset = 0;
8287                 rsurface.modelnormal3f_vertexbuffer = 0;
8288                 rsurface.modelnormal3f_bufferoffset = 0;
8289                 rsurface.modelgeneratedvertex = true;
8290         }
8291         else
8292         {
8293                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8294                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8295                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8296                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8297                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8298                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8299                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8300                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8301                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8302                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8303                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8304                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8305                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8306                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8307                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8308                 rsurface.modelgeneratedvertex = false;
8309         }
8310         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8311         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8312         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8313         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8314         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8315         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8316         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8317         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8318         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8319         rsurface.modelelement3i = model->surfmesh.data_element3i;
8320         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8321         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8322         rsurface.modelelement3s = model->surfmesh.data_element3s;
8323         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8324         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8325         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8326         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8327         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8328         rsurface.modelsurfaces = model->data_surfaces;
8329         rsurface.batchgeneratedvertex = false;
8330         rsurface.batchfirstvertex = 0;
8331         rsurface.batchnumvertices = 0;
8332         rsurface.batchfirsttriangle = 0;
8333         rsurface.batchnumtriangles = 0;
8334         rsurface.batchvertex3f  = NULL;
8335         rsurface.batchvertex3f_vertexbuffer = NULL;
8336         rsurface.batchvertex3f_bufferoffset = 0;
8337         rsurface.batchsvector3f = NULL;
8338         rsurface.batchsvector3f_vertexbuffer = NULL;
8339         rsurface.batchsvector3f_bufferoffset = 0;
8340         rsurface.batchtvector3f = NULL;
8341         rsurface.batchtvector3f_vertexbuffer = NULL;
8342         rsurface.batchtvector3f_bufferoffset = 0;
8343         rsurface.batchnormal3f  = NULL;
8344         rsurface.batchnormal3f_vertexbuffer = NULL;
8345         rsurface.batchnormal3f_bufferoffset = 0;
8346         rsurface.batchlightmapcolor4f = NULL;
8347         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8348         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8349         rsurface.batchtexcoordtexture2f = NULL;
8350         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8351         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8352         rsurface.batchtexcoordlightmap2f = NULL;
8353         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8354         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8355         rsurface.batchvertexmesh = NULL;
8356         rsurface.batchvertexmeshbuffer = NULL;
8357         rsurface.batchvertex3fbuffer = NULL;
8358         rsurface.batchelement3i = NULL;
8359         rsurface.batchelement3i_indexbuffer = NULL;
8360         rsurface.batchelement3i_bufferoffset = 0;
8361         rsurface.batchelement3s = NULL;
8362         rsurface.batchelement3s_indexbuffer = NULL;
8363         rsurface.batchelement3s_bufferoffset = 0;
8364         rsurface.passcolor4f = NULL;
8365         rsurface.passcolor4f_vertexbuffer = NULL;
8366         rsurface.passcolor4f_bufferoffset = 0;
8367         rsurface.forcecurrenttextureupdate = false;
8368 }
8369
8370 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)
8371 {
8372         rsurface.entity = r_refdef.scene.worldentity;
8373         rsurface.skeleton = NULL;
8374         rsurface.ent_skinnum = 0;
8375         rsurface.ent_qwskin = -1;
8376         rsurface.ent_flags = entflags;
8377         rsurface.shadertime = r_refdef.scene.time - shadertime;
8378         rsurface.modelnumvertices = numvertices;
8379         rsurface.modelnumtriangles = numtriangles;
8380         rsurface.matrix = *matrix;
8381         rsurface.inversematrix = *inversematrix;
8382         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8383         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8384         R_EntityMatrix(&rsurface.matrix);
8385         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8386         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8387         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8388         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8389         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8390         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8391         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8392         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8393         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8394         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8395         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8396         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8397         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);
8398         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8399         rsurface.frameblend[0].lerp = 1;
8400         rsurface.ent_alttextures = false;
8401         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8402         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8403         if (wanttangents)
8404         {
8405                 rsurface.modelvertex3f = (float *)vertex3f;
8406                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8407                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8408                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8409         }
8410         else if (wantnormals)
8411         {
8412                 rsurface.modelvertex3f = (float *)vertex3f;
8413                 rsurface.modelsvector3f = NULL;
8414                 rsurface.modeltvector3f = NULL;
8415                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8416         }
8417         else
8418         {
8419                 rsurface.modelvertex3f = (float *)vertex3f;
8420                 rsurface.modelsvector3f = NULL;
8421                 rsurface.modeltvector3f = NULL;
8422                 rsurface.modelnormal3f = NULL;
8423         }
8424         rsurface.modelvertexmesh = NULL;
8425         rsurface.modelvertexmeshbuffer = NULL;
8426         rsurface.modelvertex3fbuffer = NULL;
8427         rsurface.modelvertex3f_vertexbuffer = 0;
8428         rsurface.modelvertex3f_bufferoffset = 0;
8429         rsurface.modelsvector3f_vertexbuffer = 0;
8430         rsurface.modelsvector3f_bufferoffset = 0;
8431         rsurface.modeltvector3f_vertexbuffer = 0;
8432         rsurface.modeltvector3f_bufferoffset = 0;
8433         rsurface.modelnormal3f_vertexbuffer = 0;
8434         rsurface.modelnormal3f_bufferoffset = 0;
8435         rsurface.modelgeneratedvertex = true;
8436         rsurface.modellightmapcolor4f  = (float *)color4f;
8437         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8438         rsurface.modellightmapcolor4f_bufferoffset = 0;
8439         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8440         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8441         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8442         rsurface.modeltexcoordlightmap2f  = NULL;
8443         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8444         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8445         rsurface.modelelement3i = (int *)element3i;
8446         rsurface.modelelement3i_indexbuffer = NULL;
8447         rsurface.modelelement3i_bufferoffset = 0;
8448         rsurface.modelelement3s = (unsigned short *)element3s;
8449         rsurface.modelelement3s_indexbuffer = NULL;
8450         rsurface.modelelement3s_bufferoffset = 0;
8451         rsurface.modellightmapoffsets = NULL;
8452         rsurface.modelsurfaces = NULL;
8453         rsurface.batchgeneratedvertex = false;
8454         rsurface.batchfirstvertex = 0;
8455         rsurface.batchnumvertices = 0;
8456         rsurface.batchfirsttriangle = 0;
8457         rsurface.batchnumtriangles = 0;
8458         rsurface.batchvertex3f  = NULL;
8459         rsurface.batchvertex3f_vertexbuffer = NULL;
8460         rsurface.batchvertex3f_bufferoffset = 0;
8461         rsurface.batchsvector3f = NULL;
8462         rsurface.batchsvector3f_vertexbuffer = NULL;
8463         rsurface.batchsvector3f_bufferoffset = 0;
8464         rsurface.batchtvector3f = NULL;
8465         rsurface.batchtvector3f_vertexbuffer = NULL;
8466         rsurface.batchtvector3f_bufferoffset = 0;
8467         rsurface.batchnormal3f  = NULL;
8468         rsurface.batchnormal3f_vertexbuffer = NULL;
8469         rsurface.batchnormal3f_bufferoffset = 0;
8470         rsurface.batchlightmapcolor4f = NULL;
8471         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8472         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8473         rsurface.batchtexcoordtexture2f = NULL;
8474         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8475         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8476         rsurface.batchtexcoordlightmap2f = NULL;
8477         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8478         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8479         rsurface.batchvertexmesh = NULL;
8480         rsurface.batchvertexmeshbuffer = NULL;
8481         rsurface.batchvertex3fbuffer = NULL;
8482         rsurface.batchelement3i = NULL;
8483         rsurface.batchelement3i_indexbuffer = NULL;
8484         rsurface.batchelement3i_bufferoffset = 0;
8485         rsurface.batchelement3s = NULL;
8486         rsurface.batchelement3s_indexbuffer = NULL;
8487         rsurface.batchelement3s_bufferoffset = 0;
8488         rsurface.passcolor4f = NULL;
8489         rsurface.passcolor4f_vertexbuffer = NULL;
8490         rsurface.passcolor4f_bufferoffset = 0;
8491         rsurface.forcecurrenttextureupdate = true;
8492
8493         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8494         {
8495                 if ((wantnormals || wanttangents) && !normal3f)
8496                 {
8497                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8498                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8499                 }
8500                 if (wanttangents && !svector3f)
8501                 {
8502                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8503                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8504                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8505                 }
8506         }
8507 }
8508
8509 float RSurf_FogPoint(const float *v)
8510 {
8511         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8512         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8513         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8514         float FogHeightFade = r_refdef.fogheightfade;
8515         float fogfrac;
8516         unsigned int fogmasktableindex;
8517         if (r_refdef.fogplaneviewabove)
8518                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8519         else
8520                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8521         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8522         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8523 }
8524
8525 float RSurf_FogVertex(const float *v)
8526 {
8527         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8528         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8529         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8530         float FogHeightFade = rsurface.fogheightfade;
8531         float fogfrac;
8532         unsigned int fogmasktableindex;
8533         if (r_refdef.fogplaneviewabove)
8534                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8535         else
8536                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8537         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8538         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8539 }
8540
8541 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8542 {
8543         int i;
8544         for (i = 0;i < numelements;i++)
8545                 outelement3i[i] = inelement3i[i] + adjust;
8546 }
8547
8548 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8549 extern cvar_t gl_vbo;
8550 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8551 {
8552         int deformindex;
8553         int firsttriangle;
8554         int numtriangles;
8555         int firstvertex;
8556         int endvertex;
8557         int numvertices;
8558         int surfacefirsttriangle;
8559         int surfacenumtriangles;
8560         int surfacefirstvertex;
8561         int surfaceendvertex;
8562         int surfacenumvertices;
8563         int batchnumvertices;
8564         int batchnumtriangles;
8565         int needsupdate;
8566         int i, j;
8567         qboolean gaps;
8568         qboolean dynamicvertex;
8569         float amplitude;
8570         float animpos;
8571         float scale;
8572         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8573         float waveparms[4];
8574         q3shaderinfo_deform_t *deform;
8575         const msurface_t *surface, *firstsurface;
8576         r_vertexmesh_t *vertexmesh;
8577         if (!texturenumsurfaces)
8578                 return;
8579         // find vertex range of this surface batch
8580         gaps = false;
8581         firstsurface = texturesurfacelist[0];
8582         firsttriangle = firstsurface->num_firsttriangle;
8583         batchnumvertices = 0;
8584         batchnumtriangles = 0;
8585         firstvertex = endvertex = firstsurface->num_firstvertex;
8586         for (i = 0;i < texturenumsurfaces;i++)
8587         {
8588                 surface = texturesurfacelist[i];
8589                 if (surface != firstsurface + i)
8590                         gaps = true;
8591                 surfacefirstvertex = surface->num_firstvertex;
8592                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8593                 surfacenumvertices = surface->num_vertices;
8594                 surfacenumtriangles = surface->num_triangles;
8595                 if (firstvertex > surfacefirstvertex)
8596                         firstvertex = surfacefirstvertex;
8597                 if (endvertex < surfaceendvertex)
8598                         endvertex = surfaceendvertex;
8599                 batchnumvertices += surfacenumvertices;
8600                 batchnumtriangles += surfacenumtriangles;
8601         }
8602
8603         // we now know the vertex range used, and if there are any gaps in it
8604         rsurface.batchfirstvertex = firstvertex;
8605         rsurface.batchnumvertices = endvertex - firstvertex;
8606         rsurface.batchfirsttriangle = firsttriangle;
8607         rsurface.batchnumtriangles = batchnumtriangles;
8608
8609         // this variable holds flags for which properties have been updated that
8610         // may require regenerating vertexmesh array...
8611         needsupdate = 0;
8612
8613         // check if any dynamic vertex processing must occur
8614         dynamicvertex = false;
8615
8616         // if there is a chance of animated vertex colors, it's a dynamic batch
8617         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8618         {
8619                 dynamicvertex = true;
8620                 batchneed |= BATCHNEED_NOGAPS;
8621                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8622         }
8623
8624         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8625         {
8626                 switch (deform->deform)
8627                 {
8628                 default:
8629                 case Q3DEFORM_PROJECTIONSHADOW:
8630                 case Q3DEFORM_TEXT0:
8631                 case Q3DEFORM_TEXT1:
8632                 case Q3DEFORM_TEXT2:
8633                 case Q3DEFORM_TEXT3:
8634                 case Q3DEFORM_TEXT4:
8635                 case Q3DEFORM_TEXT5:
8636                 case Q3DEFORM_TEXT6:
8637                 case Q3DEFORM_TEXT7:
8638                 case Q3DEFORM_NONE:
8639                         break;
8640                 case Q3DEFORM_AUTOSPRITE:
8641                         dynamicvertex = true;
8642                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8643                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8644                         break;
8645                 case Q3DEFORM_AUTOSPRITE2:
8646                         dynamicvertex = true;
8647                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8648                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8649                         break;
8650                 case Q3DEFORM_NORMAL:
8651                         dynamicvertex = true;
8652                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8653                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8654                         break;
8655                 case Q3DEFORM_WAVE:
8656                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8657                                 break; // if wavefunc is a nop, ignore this transform
8658                         dynamicvertex = true;
8659                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8660                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8661                         break;
8662                 case Q3DEFORM_BULGE:
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_MOVE:
8668                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8669                                 break; // if wavefunc is a nop, ignore this transform
8670                         dynamicvertex = true;
8671                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8672                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8673                         break;
8674                 }
8675         }
8676         switch(rsurface.texture->tcgen.tcgen)
8677         {
8678         default:
8679         case Q3TCGEN_TEXTURE:
8680                 break;
8681         case Q3TCGEN_LIGHTMAP:
8682                 dynamicvertex = true;
8683                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8684                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8685                 break;
8686         case Q3TCGEN_VECTOR:
8687                 dynamicvertex = true;
8688                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8689                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8690                 break;
8691         case Q3TCGEN_ENVIRONMENT:
8692                 dynamicvertex = true;
8693                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8694                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8695                 break;
8696         }
8697         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8698         {
8699                 dynamicvertex = true;
8700                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8701                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8702         }
8703
8704         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8705         {
8706                 dynamicvertex = true;
8707                 batchneed |= BATCHNEED_NOGAPS;
8708                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8709         }
8710
8711         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8712         {
8713                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8714                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8715                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8716                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8717                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8718                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8719                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8720         }
8721
8722         // when the model data has no vertex buffer (dynamic mesh), we need to
8723         // eliminate gaps
8724         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8725                 batchneed |= BATCHNEED_NOGAPS;
8726
8727         // if needsupdate, we have to do a dynamic vertex batch for sure
8728         if (needsupdate & batchneed)
8729                 dynamicvertex = true;
8730
8731         // see if we need to build vertexmesh from arrays
8732         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8733                 dynamicvertex = true;
8734
8735         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8736         // also some drivers strongly dislike firstvertex
8737         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8738                 dynamicvertex = true;
8739
8740         rsurface.batchvertex3f = rsurface.modelvertex3f;
8741         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8742         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8743         rsurface.batchsvector3f = rsurface.modelsvector3f;
8744         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8745         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8746         rsurface.batchtvector3f = rsurface.modeltvector3f;
8747         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8748         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8749         rsurface.batchnormal3f = rsurface.modelnormal3f;
8750         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8751         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8752         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8753         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8754         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8755         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8756         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8757         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8758         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8759         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8760         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8761         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8762         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8763         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8764         rsurface.batchelement3i = rsurface.modelelement3i;
8765         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8766         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8767         rsurface.batchelement3s = rsurface.modelelement3s;
8768         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8769         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8770
8771         // if any dynamic vertex processing has to occur in software, we copy the
8772         // entire surface list together before processing to rebase the vertices
8773         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8774         //
8775         // if any gaps exist and we do not have a static vertex buffer, we have to
8776         // copy the surface list together to avoid wasting upload bandwidth on the
8777         // vertices in the gaps.
8778         //
8779         // if gaps exist and we have a static vertex buffer, we still have to
8780         // combine the index buffer ranges into one dynamic index buffer.
8781         //
8782         // in all cases we end up with data that can be drawn in one call.
8783
8784         if (!dynamicvertex)
8785         {
8786                 // static vertex data, just set pointers...
8787                 rsurface.batchgeneratedvertex = false;
8788                 // if there are gaps, we want to build a combined index buffer,
8789                 // otherwise use the original static buffer with an appropriate offset
8790                 if (gaps)
8791                 {
8792                         // build a new triangle elements array for this batch
8793                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8794                         rsurface.batchfirsttriangle = 0;
8795                         numtriangles = 0;
8796                         for (i = 0;i < texturenumsurfaces;i++)
8797                         {
8798                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8799                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8800                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8801                                 numtriangles += surfacenumtriangles;
8802                         }
8803                         rsurface.batchelement3i_indexbuffer = NULL;
8804                         rsurface.batchelement3i_bufferoffset = 0;
8805                         rsurface.batchelement3s = NULL;
8806                         rsurface.batchelement3s_indexbuffer = NULL;
8807                         rsurface.batchelement3s_bufferoffset = 0;
8808                         if (endvertex <= 65536)
8809                         {
8810                                 // make a 16bit (unsigned short) index array if possible
8811                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8812                                 for (i = 0;i < numtriangles*3;i++)
8813                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8814                         }
8815                 }
8816                 return;
8817         }
8818
8819         // something needs software processing, do it for real...
8820         // we only directly handle separate array data in this case and then
8821         // generate interleaved data if needed...
8822         rsurface.batchgeneratedvertex = true;
8823
8824         // now copy the vertex data into a combined array and make an index array
8825         // (this is what Quake3 does all the time)
8826         //if (gaps || rsurface.batchfirstvertex)
8827         {
8828                 rsurface.batchvertex3fbuffer = NULL;
8829                 rsurface.batchvertexmesh = NULL;
8830                 rsurface.batchvertexmeshbuffer = NULL;
8831                 rsurface.batchvertex3f = NULL;
8832                 rsurface.batchvertex3f_vertexbuffer = NULL;
8833                 rsurface.batchvertex3f_bufferoffset = 0;
8834                 rsurface.batchsvector3f = NULL;
8835                 rsurface.batchsvector3f_vertexbuffer = NULL;
8836                 rsurface.batchsvector3f_bufferoffset = 0;
8837                 rsurface.batchtvector3f = NULL;
8838                 rsurface.batchtvector3f_vertexbuffer = NULL;
8839                 rsurface.batchtvector3f_bufferoffset = 0;
8840                 rsurface.batchnormal3f = NULL;
8841                 rsurface.batchnormal3f_vertexbuffer = NULL;
8842                 rsurface.batchnormal3f_bufferoffset = 0;
8843                 rsurface.batchlightmapcolor4f = NULL;
8844                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8845                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8846                 rsurface.batchtexcoordtexture2f = NULL;
8847                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8848                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8849                 rsurface.batchtexcoordlightmap2f = NULL;
8850                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8851                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8852                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8853                 rsurface.batchelement3i_indexbuffer = NULL;
8854                 rsurface.batchelement3i_bufferoffset = 0;
8855                 rsurface.batchelement3s = NULL;
8856                 rsurface.batchelement3s_indexbuffer = NULL;
8857                 rsurface.batchelement3s_bufferoffset = 0;
8858                 // we'll only be setting up certain arrays as needed
8859                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8860                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8861                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8862                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8863                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8864                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8865                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8866                 {
8867                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8869                 }
8870                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8871                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8872                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8873                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8874                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8875                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8876                 numvertices = 0;
8877                 numtriangles = 0;
8878                 for (i = 0;i < texturenumsurfaces;i++)
8879                 {
8880                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8881                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8882                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8883                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8884                         // copy only the data requested
8885                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8886                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8887                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8888                         {
8889                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8890                                 {
8891                                         if (rsurface.batchvertex3f)
8892                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8893                                         else
8894                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8895                                 }
8896                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8897                                 {
8898                                         if (rsurface.modelnormal3f)
8899                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8900                                         else
8901                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8902                                 }
8903                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8904                                 {
8905                                         if (rsurface.modelsvector3f)
8906                                         {
8907                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8908                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8909                                         }
8910                                         else
8911                                         {
8912                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8913                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8914                                         }
8915                                 }
8916                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8917                                 {
8918                                         if (rsurface.modellightmapcolor4f)
8919                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8920                                         else
8921                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8922                                 }
8923                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8924                                 {
8925                                         if (rsurface.modeltexcoordtexture2f)
8926                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8927                                         else
8928                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8929                                 }
8930                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8931                                 {
8932                                         if (rsurface.modeltexcoordlightmap2f)
8933                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8934                                         else
8935                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8936                                 }
8937                         }
8938                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8939                         numvertices += surfacenumvertices;
8940                         numtriangles += surfacenumtriangles;
8941                 }
8942
8943                 // generate a 16bit index array as well if possible
8944                 // (in general, dynamic batches fit)
8945                 if (numvertices <= 65536)
8946                 {
8947                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8948                         for (i = 0;i < numtriangles*3;i++)
8949                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8950                 }
8951
8952                 // since we've copied everything, the batch now starts at 0
8953                 rsurface.batchfirstvertex = 0;
8954                 rsurface.batchnumvertices = batchnumvertices;
8955                 rsurface.batchfirsttriangle = 0;
8956                 rsurface.batchnumtriangles = batchnumtriangles;
8957         }
8958
8959         // q1bsp surfaces rendered in vertex color mode have to have colors
8960         // calculated based on lightstyles
8961         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8962         {
8963                 // generate color arrays for the surfaces in this list
8964                 int c[4];
8965                 int scale;
8966                 int size3;
8967                 const int *offsets;
8968                 const unsigned char *lm;
8969                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8970                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8971                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8972                 numvertices = 0;
8973                 for (i = 0;i < texturenumsurfaces;i++)
8974                 {
8975                         surface = texturesurfacelist[i];
8976                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8977                         surfacenumvertices = surface->num_vertices;
8978                         if (surface->lightmapinfo->samples)
8979                         {
8980                                 for (j = 0;j < surfacenumvertices;j++)
8981                                 {
8982                                         lm = surface->lightmapinfo->samples + offsets[j];
8983                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8984                                         VectorScale(lm, scale, c);
8985                                         if (surface->lightmapinfo->styles[1] != 255)
8986                                         {
8987                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8988                                                 lm += size3;
8989                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8990                                                 VectorMA(c, scale, lm, c);
8991                                                 if (surface->lightmapinfo->styles[2] != 255)
8992                                                 {
8993                                                         lm += size3;
8994                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8995                                                         VectorMA(c, scale, lm, c);
8996                                                         if (surface->lightmapinfo->styles[3] != 255)
8997                                                         {
8998                                                                 lm += size3;
8999                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9000                                                                 VectorMA(c, scale, lm, c);
9001                                                         }
9002                                                 }
9003                                         }
9004                                         c[0] >>= 7;
9005                                         c[1] >>= 7;
9006                                         c[2] >>= 7;
9007                                         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);
9008                                         numvertices++;
9009                                 }
9010                         }
9011                         else
9012                         {
9013                                 for (j = 0;j < surfacenumvertices;j++)
9014                                 {
9015                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9016                                         numvertices++;
9017                                 }
9018                         }
9019                 }
9020         }
9021
9022         // if vertices are deformed (sprite flares and things in maps, possibly
9023         // water waves, bulges and other deformations), modify the copied vertices
9024         // in place
9025         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9026         {
9027                 switch (deform->deform)
9028                 {
9029                 default:
9030                 case Q3DEFORM_PROJECTIONSHADOW:
9031                 case Q3DEFORM_TEXT0:
9032                 case Q3DEFORM_TEXT1:
9033                 case Q3DEFORM_TEXT2:
9034                 case Q3DEFORM_TEXT3:
9035                 case Q3DEFORM_TEXT4:
9036                 case Q3DEFORM_TEXT5:
9037                 case Q3DEFORM_TEXT6:
9038                 case Q3DEFORM_TEXT7:
9039                 case Q3DEFORM_NONE:
9040                         break;
9041                 case Q3DEFORM_AUTOSPRITE:
9042                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9043                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9044                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9045                         VectorNormalize(newforward);
9046                         VectorNormalize(newright);
9047                         VectorNormalize(newup);
9048 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9049 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9050 //                      rsurface.batchvertex3f_bufferoffset = 0;
9051 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9052 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9053 //                      rsurface.batchsvector3f_bufferoffset = 0;
9054 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9055 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9056 //                      rsurface.batchtvector3f_bufferoffset = 0;
9057 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9058 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9059 //                      rsurface.batchnormal3f_bufferoffset = 0;
9060                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9061                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9062                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9063                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9064                                 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);
9065                         // a single autosprite surface can contain multiple sprites...
9066                         for (j = 0;j < batchnumvertices - 3;j += 4)
9067                         {
9068                                 VectorClear(center);
9069                                 for (i = 0;i < 4;i++)
9070                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9071                                 VectorScale(center, 0.25f, center);
9072                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9073                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9074                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9075                                 for (i = 0;i < 4;i++)
9076                                 {
9077                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9078                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9079                                 }
9080                         }
9081                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9082                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9083                         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);
9084                         break;
9085                 case Q3DEFORM_AUTOSPRITE2:
9086                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9087                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9088                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9089                         VectorNormalize(newforward);
9090                         VectorNormalize(newright);
9091                         VectorNormalize(newup);
9092 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9093 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9094 //                      rsurface.batchvertex3f_bufferoffset = 0;
9095                         {
9096                                 const float *v1, *v2;
9097                                 vec3_t start, end;
9098                                 float f, l;
9099                                 struct
9100                                 {
9101                                         float length2;
9102                                         const float *v1;
9103                                         const float *v2;
9104                                 }
9105                                 shortest[2];
9106                                 memset(shortest, 0, sizeof(shortest));
9107                                 // a single autosprite surface can contain multiple sprites...
9108                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9109                                 {
9110                                         VectorClear(center);
9111                                         for (i = 0;i < 4;i++)
9112                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9113                                         VectorScale(center, 0.25f, center);
9114                                         // find the two shortest edges, then use them to define the
9115                                         // axis vectors for rotating around the central axis
9116                                         for (i = 0;i < 6;i++)
9117                                         {
9118                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9119                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9120                                                 l = VectorDistance2(v1, v2);
9121                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9122                                                 if (v1[2] != v2[2])
9123                                                         l += (1.0f / 1024.0f);
9124                                                 if (shortest[0].length2 > l || i == 0)
9125                                                 {
9126                                                         shortest[1] = shortest[0];
9127                                                         shortest[0].length2 = l;
9128                                                         shortest[0].v1 = v1;
9129                                                         shortest[0].v2 = v2;
9130                                                 }
9131                                                 else if (shortest[1].length2 > l || i == 1)
9132                                                 {
9133                                                         shortest[1].length2 = l;
9134                                                         shortest[1].v1 = v1;
9135                                                         shortest[1].v2 = v2;
9136                                                 }
9137                                         }
9138                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9139                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9140                                         // this calculates the right vector from the shortest edge
9141                                         // and the up vector from the edge midpoints
9142                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9143                                         VectorNormalize(right);
9144                                         VectorSubtract(end, start, up);
9145                                         VectorNormalize(up);
9146                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9147                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9148                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9149                                         VectorNegate(forward, forward);
9150                                         VectorReflect(forward, 0, up, forward);
9151                                         VectorNormalize(forward);
9152                                         CrossProduct(up, forward, newright);
9153                                         VectorNormalize(newright);
9154                                         // rotate the quad around the up axis vector, this is made
9155                                         // especially easy by the fact we know the quad is flat,
9156                                         // so we only have to subtract the center position and
9157                                         // measure distance along the right vector, and then
9158                                         // multiply that by the newright vector and add back the
9159                                         // center position
9160                                         // we also need to subtract the old position to undo the
9161                                         // displacement from the center, which we do with a
9162                                         // DotProduct, the subtraction/addition of center is also
9163                                         // optimized into DotProducts here
9164                                         l = DotProduct(right, center);
9165                                         for (i = 0;i < 4;i++)
9166                                         {
9167                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9168                                                 f = DotProduct(right, v1) - l;
9169                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9170                                         }
9171                                 }
9172                         }
9173                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9174                         {
9175 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9176 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9177 //                              rsurface.batchnormal3f_bufferoffset = 0;
9178                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9179                         }
9180                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9181                         {
9182 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9183 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9184 //                              rsurface.batchsvector3f_bufferoffset = 0;
9185 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9186 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9187 //                              rsurface.batchtvector3f_bufferoffset = 0;
9188                                 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);
9189                         }
9190                         break;
9191                 case Q3DEFORM_NORMAL:
9192                         // deform the normals to make reflections wavey
9193                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9194                         rsurface.batchnormal3f_vertexbuffer = NULL;
9195                         rsurface.batchnormal3f_bufferoffset = 0;
9196                         for (j = 0;j < batchnumvertices;j++)
9197                         {
9198                                 float vertex[3];
9199                                 float *normal = rsurface.batchnormal3f + 3*j;
9200                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9201                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9202                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9203                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9204                                 VectorNormalize(normal);
9205                         }
9206                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9207                         {
9208 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9209 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9210 //                              rsurface.batchsvector3f_bufferoffset = 0;
9211 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9212 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9213 //                              rsurface.batchtvector3f_bufferoffset = 0;
9214                                 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);
9215                         }
9216                         break;
9217                 case Q3DEFORM_WAVE:
9218                         // deform vertex array to make wavey water and flags and such
9219                         waveparms[0] = deform->waveparms[0];
9220                         waveparms[1] = deform->waveparms[1];
9221                         waveparms[2] = deform->waveparms[2];
9222                         waveparms[3] = deform->waveparms[3];
9223                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9224                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9225                         // this is how a divisor of vertex influence on deformation
9226                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9227                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9228 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9229 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9230 //                      rsurface.batchvertex3f_bufferoffset = 0;
9231 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9232 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9233 //                      rsurface.batchnormal3f_bufferoffset = 0;
9234                         for (j = 0;j < batchnumvertices;j++)
9235                         {
9236                                 // if the wavefunc depends on time, evaluate it per-vertex
9237                                 if (waveparms[3])
9238                                 {
9239                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9240                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9241                                 }
9242                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9243                         }
9244                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9245                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9246                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9247                         {
9248 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9249 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9250 //                              rsurface.batchsvector3f_bufferoffset = 0;
9251 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9252 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9253 //                              rsurface.batchtvector3f_bufferoffset = 0;
9254                                 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);
9255                         }
9256                         break;
9257                 case Q3DEFORM_BULGE:
9258                         // deform vertex array to make the surface have moving bulges
9259 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9260 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9261 //                      rsurface.batchvertex3f_bufferoffset = 0;
9262 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9263 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9264 //                      rsurface.batchnormal3f_bufferoffset = 0;
9265                         for (j = 0;j < batchnumvertices;j++)
9266                         {
9267                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9268                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9269                         }
9270                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9271                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9272                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9273                         {
9274 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9275 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9276 //                              rsurface.batchsvector3f_bufferoffset = 0;
9277 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9278 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9279 //                              rsurface.batchtvector3f_bufferoffset = 0;
9280                                 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);
9281                         }
9282                         break;
9283                 case Q3DEFORM_MOVE:
9284                         // deform vertex array
9285                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9286                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9287                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9288                         VectorScale(deform->parms, scale, waveparms);
9289 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9290 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9291 //                      rsurface.batchvertex3f_bufferoffset = 0;
9292                         for (j = 0;j < batchnumvertices;j++)
9293                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9294                         break;
9295                 }
9296         }
9297
9298         // generate texcoords based on the chosen texcoord source
9299         switch(rsurface.texture->tcgen.tcgen)
9300         {
9301         default:
9302         case Q3TCGEN_TEXTURE:
9303                 break;
9304         case Q3TCGEN_LIGHTMAP:
9305 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9306 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9307 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9308                 if (rsurface.batchtexcoordlightmap2f)
9309                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9310                 break;
9311         case Q3TCGEN_VECTOR:
9312 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9313 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9314 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9315                 for (j = 0;j < batchnumvertices;j++)
9316                 {
9317                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9318                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9319                 }
9320                 break;
9321         case Q3TCGEN_ENVIRONMENT:
9322                 // make environment reflections using a spheremap
9323                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9324                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9325                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9326                 for (j = 0;j < batchnumvertices;j++)
9327                 {
9328                         // identical to Q3A's method, but executed in worldspace so
9329                         // carried models can be shiny too
9330
9331                         float viewer[3], d, reflected[3], worldreflected[3];
9332
9333                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9334                         // VectorNormalize(viewer);
9335
9336                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9337
9338                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9339                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9340                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9341                         // note: this is proportinal to viewer, so we can normalize later
9342
9343                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9344                         VectorNormalize(worldreflected);
9345
9346                         // note: this sphere map only uses world x and z!
9347                         // so positive and negative y will LOOK THE SAME.
9348                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9349                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9350                 }
9351                 break;
9352         }
9353         // the only tcmod that needs software vertex processing is turbulent, so
9354         // check for it here and apply the changes if needed
9355         // and we only support that as the first one
9356         // (handling a mixture of turbulent and other tcmods would be problematic
9357         //  without punting it entirely to a software path)
9358         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9359         {
9360                 amplitude = rsurface.texture->tcmods[0].parms[1];
9361                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9362 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9363 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9364 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9365                 for (j = 0;j < batchnumvertices;j++)
9366                 {
9367                         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);
9368                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9369                 }
9370         }
9371
9372         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9373         {
9374                 // convert the modified arrays to vertex structs
9375 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9376 //              rsurface.batchvertexmeshbuffer = NULL;
9377                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9378                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9379                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9380                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9381                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9382                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9383                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9384                 {
9385                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9386                         {
9387                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9388                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9389                         }
9390                 }
9391                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9392                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9393                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9394                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9395                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9396                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9397                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9398                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9399                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9400         }
9401 }
9402
9403 void RSurf_DrawBatch(void)
9404 {
9405         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9406         // through the pipeline, killing it earlier in the pipeline would have
9407         // per-surface overhead rather than per-batch overhead, so it's best to
9408         // reject it here, before it hits glDraw.
9409         if (rsurface.batchnumtriangles == 0)
9410                 return;
9411 #if 0
9412         // batch debugging code
9413         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9414         {
9415                 int i;
9416                 int j;
9417                 int c;
9418                 const int *e;
9419                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9420                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9421                 {
9422                         c = e[i];
9423                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9424                         {
9425                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9426                                 {
9427                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9428                                                 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);
9429                                         break;
9430                                 }
9431                         }
9432                 }
9433         }
9434 #endif
9435         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);
9436 }
9437
9438 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9439 {
9440         // pick the closest matching water plane
9441         int planeindex, vertexindex, bestplaneindex = -1;
9442         float d, bestd;
9443         vec3_t vert;
9444         const float *v;
9445         r_waterstate_waterplane_t *p;
9446         qboolean prepared = false;
9447         bestd = 0;
9448         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9449         {
9450                 if(p->camera_entity != rsurface.texture->camera_entity)
9451                         continue;
9452                 d = 0;
9453                 if(!prepared)
9454                 {
9455                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9456                         prepared = true;
9457                         if(rsurface.batchnumvertices == 0)
9458                                 break;
9459                 }
9460                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9461                 {
9462                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9463                         d += fabs(PlaneDiff(vert, &p->plane));
9464                 }
9465                 if (bestd > d || bestplaneindex < 0)
9466                 {
9467                         bestd = d;
9468                         bestplaneindex = planeindex;
9469                 }
9470         }
9471         return bestplaneindex;
9472         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9473         // this situation though, as it might be better to render single larger
9474         // batches with useless stuff (backface culled for example) than to
9475         // render multiple smaller batches
9476 }
9477
9478 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9479 {
9480         int i;
9481         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9482         rsurface.passcolor4f_vertexbuffer = 0;
9483         rsurface.passcolor4f_bufferoffset = 0;
9484         for (i = 0;i < rsurface.batchnumvertices;i++)
9485                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9486 }
9487
9488 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9489 {
9490         int i;
9491         float f;
9492         const float *v;
9493         const float *c;
9494         float *c2;
9495         if (rsurface.passcolor4f)
9496         {
9497                 // generate color arrays
9498                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9499                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9500                 rsurface.passcolor4f_vertexbuffer = 0;
9501                 rsurface.passcolor4f_bufferoffset = 0;
9502                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9503                 {
9504                         f = RSurf_FogVertex(v);
9505                         c2[0] = c[0] * f;
9506                         c2[1] = c[1] * f;
9507                         c2[2] = c[2] * f;
9508                         c2[3] = c[3];
9509                 }
9510         }
9511         else
9512         {
9513                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9514                 rsurface.passcolor4f_vertexbuffer = 0;
9515                 rsurface.passcolor4f_bufferoffset = 0;
9516                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9517                 {
9518                         f = RSurf_FogVertex(v);
9519                         c2[0] = f;
9520                         c2[1] = f;
9521                         c2[2] = f;
9522                         c2[3] = 1;
9523                 }
9524         }
9525 }
9526
9527 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9528 {
9529         int i;
9530         float f;
9531         const float *v;
9532         const float *c;
9533         float *c2;
9534         if (!rsurface.passcolor4f)
9535                 return;
9536         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9537         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9538         rsurface.passcolor4f_vertexbuffer = 0;
9539         rsurface.passcolor4f_bufferoffset = 0;
9540         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)
9541         {
9542                 f = RSurf_FogVertex(v);
9543                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9544                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9545                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9546                 c2[3] = c[3];
9547         }
9548 }
9549
9550 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9551 {
9552         int i;
9553         const float *c;
9554         float *c2;
9555         if (!rsurface.passcolor4f)
9556                 return;
9557         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9558         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9559         rsurface.passcolor4f_vertexbuffer = 0;
9560         rsurface.passcolor4f_bufferoffset = 0;
9561         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9562         {
9563                 c2[0] = c[0] * r;
9564                 c2[1] = c[1] * g;
9565                 c2[2] = c[2] * b;
9566                 c2[3] = c[3] * a;
9567         }
9568 }
9569
9570 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9571 {
9572         int i;
9573         const float *c;
9574         float *c2;
9575         if (!rsurface.passcolor4f)
9576                 return;
9577         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9578         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9579         rsurface.passcolor4f_vertexbuffer = 0;
9580         rsurface.passcolor4f_bufferoffset = 0;
9581         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9582         {
9583                 c2[0] = c[0] + r_refdef.scene.ambient;
9584                 c2[1] = c[1] + r_refdef.scene.ambient;
9585                 c2[2] = c[2] + r_refdef.scene.ambient;
9586                 c2[3] = c[3];
9587         }
9588 }
9589
9590 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9591 {
9592         // TODO: optimize
9593         rsurface.passcolor4f = NULL;
9594         rsurface.passcolor4f_vertexbuffer = 0;
9595         rsurface.passcolor4f_bufferoffset = 0;
9596         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9597         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9598         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9599         GL_Color(r, g, b, a);
9600         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9601         RSurf_DrawBatch();
9602 }
9603
9604 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9605 {
9606         // TODO: optimize applyfog && applycolor case
9607         // just apply fog if necessary, and tint the fog color array if necessary
9608         rsurface.passcolor4f = NULL;
9609         rsurface.passcolor4f_vertexbuffer = 0;
9610         rsurface.passcolor4f_bufferoffset = 0;
9611         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9612         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9613         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9614         GL_Color(r, g, b, a);
9615         RSurf_DrawBatch();
9616 }
9617
9618 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9619 {
9620         // TODO: optimize
9621         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9622         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9623         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9624         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9625         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9626         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9627         GL_Color(r, g, b, a);
9628         RSurf_DrawBatch();
9629 }
9630
9631 static void RSurf_DrawBatch_GL11_ClampColor(void)
9632 {
9633         int i;
9634         const float *c1;
9635         float *c2;
9636         if (!rsurface.passcolor4f)
9637                 return;
9638         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9639         {
9640                 c2[0] = bound(0.0f, c1[0], 1.0f);
9641                 c2[1] = bound(0.0f, c1[1], 1.0f);
9642                 c2[2] = bound(0.0f, c1[2], 1.0f);
9643                 c2[3] = bound(0.0f, c1[3], 1.0f);
9644         }
9645 }
9646
9647 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9648 {
9649         int i;
9650         float f;
9651         const float *v;
9652         const float *n;
9653         float *c;
9654         //vec3_t eyedir;
9655
9656         // fake shading
9657         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9658         rsurface.passcolor4f_vertexbuffer = 0;
9659         rsurface.passcolor4f_bufferoffset = 0;
9660         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)
9661         {
9662                 f = -DotProduct(r_refdef.view.forward, n);
9663                 f = max(0, f);
9664                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9665                 f *= r_refdef.lightmapintensity;
9666                 Vector4Set(c, f, f, f, 1);
9667         }
9668 }
9669
9670 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9671 {
9672         RSurf_DrawBatch_GL11_ApplyFakeLight();
9673         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9674         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9675         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9676         GL_Color(r, g, b, a);
9677         RSurf_DrawBatch();
9678 }
9679
9680 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9681 {
9682         int i;
9683         float f;
9684         float alpha;
9685         const float *v;
9686         const float *n;
9687         float *c;
9688         vec3_t ambientcolor;
9689         vec3_t diffusecolor;
9690         vec3_t lightdir;
9691         // TODO: optimize
9692         // model lighting
9693         VectorCopy(rsurface.modellight_lightdir, lightdir);
9694         f = 0.5f * r_refdef.lightmapintensity;
9695         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9696         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9697         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9698         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9699         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9700         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9701         alpha = *a;
9702         if (VectorLength2(diffusecolor) > 0)
9703         {
9704                 // q3-style directional shading
9705                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9706                 rsurface.passcolor4f_vertexbuffer = 0;
9707                 rsurface.passcolor4f_bufferoffset = 0;
9708                 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)
9709                 {
9710                         if ((f = DotProduct(n, lightdir)) > 0)
9711                                 VectorMA(ambientcolor, f, diffusecolor, c);
9712                         else
9713                                 VectorCopy(ambientcolor, c);
9714                         c[3] = alpha;
9715                 }
9716                 *r = 1;
9717                 *g = 1;
9718                 *b = 1;
9719                 *a = 1;
9720                 *applycolor = false;
9721         }
9722         else
9723         {
9724                 *r = ambientcolor[0];
9725                 *g = ambientcolor[1];
9726                 *b = ambientcolor[2];
9727                 rsurface.passcolor4f = NULL;
9728                 rsurface.passcolor4f_vertexbuffer = 0;
9729                 rsurface.passcolor4f_bufferoffset = 0;
9730         }
9731 }
9732
9733 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9734 {
9735         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9736         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9737         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9738         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9739         GL_Color(r, g, b, a);
9740         RSurf_DrawBatch();
9741 }
9742
9743 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9744 {
9745         int i;
9746         float f;
9747         const float *v;
9748         float *c;
9749
9750         // fake shading
9751         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9752         rsurface.passcolor4f_vertexbuffer = 0;
9753         rsurface.passcolor4f_bufferoffset = 0;
9754
9755         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9756         {
9757                 f = 1 - RSurf_FogVertex(v);
9758                 c[0] = r;
9759                 c[1] = g;
9760                 c[2] = b;
9761                 c[3] = f * a;
9762         }
9763 }
9764
9765 void RSurf_SetupDepthAndCulling(void)
9766 {
9767         // submodels are biased to avoid z-fighting with world surfaces that they
9768         // may be exactly overlapping (avoids z-fighting artifacts on certain
9769         // doors and things in Quake maps)
9770         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9771         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9772         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9773         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9774 }
9775
9776 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9777 {
9778         // transparent sky would be ridiculous
9779         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9780                 return;
9781         R_SetupShader_Generic_NoTexture(false, false);
9782         skyrenderlater = true;
9783         RSurf_SetupDepthAndCulling();
9784         GL_DepthMask(true);
9785         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9786         // skymasking on them, and Quake3 never did sky masking (unlike
9787         // software Quake and software Quake2), so disable the sky masking
9788         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9789         // and skymasking also looks very bad when noclipping outside the
9790         // level, so don't use it then either.
9791         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9792         {
9793                 R_Mesh_ResetTextureState();
9794                 if (skyrendermasked)
9795                 {
9796                         R_SetupShader_DepthOrShadow(false, false);
9797                         // depth-only (masking)
9798                         GL_ColorMask(0,0,0,0);
9799                         // just to make sure that braindead drivers don't draw
9800                         // anything despite that colormask...
9801                         GL_BlendFunc(GL_ZERO, GL_ONE);
9802                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9803                         if (rsurface.batchvertex3fbuffer)
9804                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9805                         else
9806                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9807                 }
9808                 else
9809                 {
9810                         R_SetupShader_Generic_NoTexture(false, false);
9811                         // fog sky
9812                         GL_BlendFunc(GL_ONE, GL_ZERO);
9813                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9814                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9815                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9816                 }
9817                 RSurf_DrawBatch();
9818                 if (skyrendermasked)
9819                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9820         }
9821         R_Mesh_ResetTextureState();
9822         GL_Color(1, 1, 1, 1);
9823 }
9824
9825 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9826 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9827 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9828 {
9829         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9830                 return;
9831         if (prepass)
9832         {
9833                 // render screenspace normalmap to texture
9834                 GL_DepthMask(true);
9835                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9836                 RSurf_DrawBatch();
9837                 return;
9838         }
9839
9840         // bind lightmap texture
9841
9842         // water/refraction/reflection/camera surfaces have to be handled specially
9843         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9844         {
9845                 int start, end, startplaneindex;
9846                 for (start = 0;start < texturenumsurfaces;start = end)
9847                 {
9848                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9849                         if(startplaneindex < 0)
9850                         {
9851                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9852                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9853                                 end = start + 1;
9854                                 continue;
9855                         }
9856                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9857                                 ;
9858                         // now that we have a batch using the same planeindex, render it
9859                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9860                         {
9861                                 // render water or distortion background
9862                                 GL_DepthMask(true);
9863                                 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);
9864                                 RSurf_DrawBatch();
9865                                 // blend surface on top
9866                                 GL_DepthMask(false);
9867                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9868                                 RSurf_DrawBatch();
9869                         }
9870                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9871                         {
9872                                 // render surface with reflection texture as input
9873                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9874                                 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);
9875                                 RSurf_DrawBatch();
9876                         }
9877                 }
9878                 return;
9879         }
9880
9881         // render surface batch normally
9882         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9883         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);
9884         RSurf_DrawBatch();
9885 }
9886
9887 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9888 {
9889         // OpenGL 1.3 path - anything not completely ancient
9890         qboolean applycolor;
9891         qboolean applyfog;
9892         int layerindex;
9893         const texturelayer_t *layer;
9894         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);
9895         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9896
9897         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9898         {
9899                 vec4_t layercolor;
9900                 int layertexrgbscale;
9901                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9902                 {
9903                         if (layerindex == 0)
9904                                 GL_AlphaTest(true);
9905                         else
9906                         {
9907                                 GL_AlphaTest(false);
9908                                 GL_DepthFunc(GL_EQUAL);
9909                         }
9910                 }
9911                 GL_DepthMask(layer->depthmask && writedepth);
9912                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9913                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9914                 {
9915                         layertexrgbscale = 4;
9916                         VectorScale(layer->color, 0.25f, layercolor);
9917                 }
9918                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9919                 {
9920                         layertexrgbscale = 2;
9921                         VectorScale(layer->color, 0.5f, layercolor);
9922                 }
9923                 else
9924                 {
9925                         layertexrgbscale = 1;
9926                         VectorScale(layer->color, 1.0f, layercolor);
9927                 }
9928                 layercolor[3] = layer->color[3];
9929                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9930                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9931                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9932                 switch (layer->type)
9933                 {
9934                 case TEXTURELAYERTYPE_LITTEXTURE:
9935                         // single-pass lightmapped texture with 2x rgbscale
9936                         R_Mesh_TexBind(0, r_texture_white);
9937                         R_Mesh_TexMatrix(0, NULL);
9938                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9939                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9940                         R_Mesh_TexBind(1, layer->texture);
9941                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9942                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9943                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9944                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9945                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9946                         else if (FAKELIGHT_ENABLED)
9947                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9948                         else if (rsurface.uselightmaptexture)
9949                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9950                         else
9951                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9952                         break;
9953                 case TEXTURELAYERTYPE_TEXTURE:
9954                         // singletexture unlit texture with transparency support
9955                         R_Mesh_TexBind(0, layer->texture);
9956                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9957                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9958                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9959                         R_Mesh_TexBind(1, 0);
9960                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9961                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9962                         break;
9963                 case TEXTURELAYERTYPE_FOG:
9964                         // singletexture fogging
9965                         if (layer->texture)
9966                         {
9967                                 R_Mesh_TexBind(0, layer->texture);
9968                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9969                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9970                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9971                         }
9972                         else
9973                         {
9974                                 R_Mesh_TexBind(0, 0);
9975                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9976                         }
9977                         R_Mesh_TexBind(1, 0);
9978                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9979                         // generate a color array for the fog pass
9980                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9981                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9982                         RSurf_DrawBatch();
9983                         break;
9984                 default:
9985                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9986                 }
9987         }
9988         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9989         {
9990                 GL_DepthFunc(GL_LEQUAL);
9991                 GL_AlphaTest(false);
9992         }
9993 }
9994
9995 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9996 {
9997         // OpenGL 1.1 - crusty old voodoo path
9998         qboolean applyfog;
9999         int layerindex;
10000         const texturelayer_t *layer;
10001         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);
10002         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10003
10004         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10005         {
10006                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10007                 {
10008                         if (layerindex == 0)
10009                                 GL_AlphaTest(true);
10010                         else
10011                         {
10012                                 GL_AlphaTest(false);
10013                                 GL_DepthFunc(GL_EQUAL);
10014                         }
10015                 }
10016                 GL_DepthMask(layer->depthmask && writedepth);
10017                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10018                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10019                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10020                 switch (layer->type)
10021                 {
10022                 case TEXTURELAYERTYPE_LITTEXTURE:
10023                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10024                         {
10025                                 // two-pass lit texture with 2x rgbscale
10026                                 // first the lightmap pass
10027                                 R_Mesh_TexBind(0, r_texture_white);
10028                                 R_Mesh_TexMatrix(0, NULL);
10029                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10030                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10031                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10032                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10033                                 else if (FAKELIGHT_ENABLED)
10034                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10035                                 else if (rsurface.uselightmaptexture)
10036                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10037                                 else
10038                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10039                                 // then apply the texture to it
10040                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10041                                 R_Mesh_TexBind(0, layer->texture);
10042                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10043                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10044                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10045                                 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);
10046                         }
10047                         else
10048                         {
10049                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10050                                 R_Mesh_TexBind(0, layer->texture);
10051                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10052                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10053                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10054                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10055                                         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);
10056                                 else
10057                                         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);
10058                         }
10059                         break;
10060                 case TEXTURELAYERTYPE_TEXTURE:
10061                         // singletexture unlit texture with transparency support
10062                         R_Mesh_TexBind(0, layer->texture);
10063                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10064                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10065                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10066                         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);
10067                         break;
10068                 case TEXTURELAYERTYPE_FOG:
10069                         // singletexture fogging
10070                         if (layer->texture)
10071                         {
10072                                 R_Mesh_TexBind(0, layer->texture);
10073                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10074                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10075                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10076                         }
10077                         else
10078                         {
10079                                 R_Mesh_TexBind(0, 0);
10080                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10081                         }
10082                         // generate a color array for the fog pass
10083                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10084                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10085                         RSurf_DrawBatch();
10086                         break;
10087                 default:
10088                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10089                 }
10090         }
10091         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10092         {
10093                 GL_DepthFunc(GL_LEQUAL);
10094                 GL_AlphaTest(false);
10095         }
10096 }
10097
10098 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10099 {
10100         int vi;
10101         int j;
10102         r_vertexgeneric_t *batchvertex;
10103         float c[4];
10104
10105 //      R_Mesh_ResetTextureState();
10106         R_SetupShader_Generic_NoTexture(false, false);
10107
10108         if(rsurface.texture && rsurface.texture->currentskinframe)
10109         {
10110                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10111                 c[3] *= rsurface.texture->currentalpha;
10112         }
10113         else
10114         {
10115                 c[0] = 1;
10116                 c[1] = 0;
10117                 c[2] = 1;
10118                 c[3] = 1;
10119         }
10120
10121         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10122         {
10123                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10124                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10125                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10126         }
10127
10128         // brighten it up (as texture value 127 means "unlit")
10129         c[0] *= 2 * r_refdef.view.colorscale;
10130         c[1] *= 2 * r_refdef.view.colorscale;
10131         c[2] *= 2 * r_refdef.view.colorscale;
10132
10133         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10134                 c[3] *= r_wateralpha.value;
10135
10136         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10137         {
10138                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10139                 GL_DepthMask(false);
10140         }
10141         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10142         {
10143                 GL_BlendFunc(GL_ONE, GL_ONE);
10144                 GL_DepthMask(false);
10145         }
10146         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10147         {
10148                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10149                 GL_DepthMask(false);
10150         }
10151         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10152         {
10153                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10154                 GL_DepthMask(false);
10155         }
10156         else
10157         {
10158                 GL_BlendFunc(GL_ONE, GL_ZERO);
10159                 GL_DepthMask(writedepth);
10160         }
10161
10162         if (r_showsurfaces.integer == 3)
10163         {
10164                 rsurface.passcolor4f = NULL;
10165
10166                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10167                 {
10168                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10169
10170                         rsurface.passcolor4f = NULL;
10171                         rsurface.passcolor4f_vertexbuffer = 0;
10172                         rsurface.passcolor4f_bufferoffset = 0;
10173                 }
10174                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10175                 {
10176                         qboolean applycolor = true;
10177                         float one = 1.0;
10178
10179                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10180
10181                         r_refdef.lightmapintensity = 1;
10182                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10183                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10184                 }
10185                 else if (FAKELIGHT_ENABLED)
10186                 {
10187                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10188
10189                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10190                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10191                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10192                 }
10193                 else
10194                 {
10195                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10196
10197                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10198                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10199                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10200                 }
10201
10202                 if(!rsurface.passcolor4f)
10203                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10204
10205                 RSurf_DrawBatch_GL11_ApplyAmbient();
10206                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10207                 if(r_refdef.fogenabled)
10208                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10209                 RSurf_DrawBatch_GL11_ClampColor();
10210
10211                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10212                 R_SetupShader_Generic_NoTexture(false, false);
10213                 RSurf_DrawBatch();
10214         }
10215         else if (!r_refdef.view.showdebug)
10216         {
10217                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10218                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10219                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10220                 {
10221                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10222                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10223                 }
10224                 R_Mesh_PrepareVertices_Generic_Unlock();
10225                 RSurf_DrawBatch();
10226         }
10227         else if (r_showsurfaces.integer == 4)
10228         {
10229                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10230                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10231                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10232                 {
10233                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10234                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10235                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10236                 }
10237                 R_Mesh_PrepareVertices_Generic_Unlock();
10238                 RSurf_DrawBatch();
10239         }
10240         else if (r_showsurfaces.integer == 2)
10241         {
10242                 const int *e;
10243                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10244                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10245                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10246                 {
10247                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10248                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10249                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10250                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10251                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10252                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10253                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10254                 }
10255                 R_Mesh_PrepareVertices_Generic_Unlock();
10256                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10257         }
10258         else
10259         {
10260                 int texturesurfaceindex;
10261                 int k;
10262                 const msurface_t *surface;
10263                 float surfacecolor4f[4];
10264                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10265                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10266                 vi = 0;
10267                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10268                 {
10269                         surface = texturesurfacelist[texturesurfaceindex];
10270                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10271                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10272                         for (j = 0;j < surface->num_vertices;j++)
10273                         {
10274                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10275                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10276                                 vi++;
10277                         }
10278                 }
10279                 R_Mesh_PrepareVertices_Generic_Unlock();
10280                 RSurf_DrawBatch();
10281         }
10282 }
10283
10284 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10285 {
10286         CHECKGLERROR
10287         RSurf_SetupDepthAndCulling();
10288         if (r_showsurfaces.integer)
10289         {
10290                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10291                 return;
10292         }
10293         switch (vid.renderpath)
10294         {
10295         case RENDERPATH_GL20:
10296         case RENDERPATH_D3D9:
10297         case RENDERPATH_D3D10:
10298         case RENDERPATH_D3D11:
10299         case RENDERPATH_SOFT:
10300         case RENDERPATH_GLES2:
10301                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10302                 break;
10303         case RENDERPATH_GL13:
10304         case RENDERPATH_GLES1:
10305                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10306                 break;
10307         case RENDERPATH_GL11:
10308                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10309                 break;
10310         }
10311         CHECKGLERROR
10312 }
10313
10314 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10315 {
10316         CHECKGLERROR
10317         RSurf_SetupDepthAndCulling();
10318         if (r_showsurfaces.integer)
10319         {
10320                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10321                 return;
10322         }
10323         switch (vid.renderpath)
10324         {
10325         case RENDERPATH_GL20:
10326         case RENDERPATH_D3D9:
10327         case RENDERPATH_D3D10:
10328         case RENDERPATH_D3D11:
10329         case RENDERPATH_SOFT:
10330         case RENDERPATH_GLES2:
10331                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10332                 break;
10333         case RENDERPATH_GL13:
10334         case RENDERPATH_GLES1:
10335                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10336                 break;
10337         case RENDERPATH_GL11:
10338                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10339                 break;
10340         }
10341         CHECKGLERROR
10342 }
10343
10344 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10345 {
10346         int i, j;
10347         int texturenumsurfaces, endsurface;
10348         texture_t *texture;
10349         const msurface_t *surface;
10350         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10351
10352         // if the model is static it doesn't matter what value we give for
10353         // wantnormals and wanttangents, so this logic uses only rules applicable
10354         // to a model, knowing that they are meaningless otherwise
10355         if (ent == r_refdef.scene.worldentity)
10356                 RSurf_ActiveWorldEntity();
10357         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10358                 RSurf_ActiveModelEntity(ent, false, false, false);
10359         else
10360         {
10361                 switch (vid.renderpath)
10362                 {
10363                 case RENDERPATH_GL20:
10364                 case RENDERPATH_D3D9:
10365                 case RENDERPATH_D3D10:
10366                 case RENDERPATH_D3D11:
10367                 case RENDERPATH_SOFT:
10368                 case RENDERPATH_GLES2:
10369                         RSurf_ActiveModelEntity(ent, true, true, false);
10370                         break;
10371                 case RENDERPATH_GL11:
10372                 case RENDERPATH_GL13:
10373                 case RENDERPATH_GLES1:
10374                         RSurf_ActiveModelEntity(ent, true, false, false);
10375                         break;
10376                 }
10377         }
10378
10379         if (r_transparentdepthmasking.integer)
10380         {
10381                 qboolean setup = false;
10382                 for (i = 0;i < numsurfaces;i = j)
10383                 {
10384                         j = i + 1;
10385                         surface = rsurface.modelsurfaces + surfacelist[i];
10386                         texture = surface->texture;
10387                         rsurface.texture = R_GetCurrentTexture(texture);
10388                         rsurface.lightmaptexture = NULL;
10389                         rsurface.deluxemaptexture = NULL;
10390                         rsurface.uselightmaptexture = false;
10391                         // scan ahead until we find a different texture
10392                         endsurface = min(i + 1024, numsurfaces);
10393                         texturenumsurfaces = 0;
10394                         texturesurfacelist[texturenumsurfaces++] = surface;
10395                         for (;j < endsurface;j++)
10396                         {
10397                                 surface = rsurface.modelsurfaces + surfacelist[j];
10398                                 if (texture != surface->texture)
10399                                         break;
10400                                 texturesurfacelist[texturenumsurfaces++] = surface;
10401                         }
10402                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10403                                 continue;
10404                         // render the range of surfaces as depth
10405                         if (!setup)
10406                         {
10407                                 setup = true;
10408                                 GL_ColorMask(0,0,0,0);
10409                                 GL_Color(1,1,1,1);
10410                                 GL_DepthTest(true);
10411                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10412                                 GL_DepthMask(true);
10413 //                              R_Mesh_ResetTextureState();
10414                                 R_SetupShader_DepthOrShadow(false, false);
10415                         }
10416                         RSurf_SetupDepthAndCulling();
10417                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10418                         if (rsurface.batchvertex3fbuffer)
10419                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10420                         else
10421                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10422                         RSurf_DrawBatch();
10423                 }
10424                 if (setup)
10425                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10426         }
10427
10428         for (i = 0;i < numsurfaces;i = j)
10429         {
10430                 j = i + 1;
10431                 surface = rsurface.modelsurfaces + surfacelist[i];
10432                 texture = surface->texture;
10433                 rsurface.texture = R_GetCurrentTexture(texture);
10434                 // scan ahead until we find a different texture
10435                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10436                 texturenumsurfaces = 0;
10437                 texturesurfacelist[texturenumsurfaces++] = surface;
10438                 if(FAKELIGHT_ENABLED)
10439                 {
10440                         rsurface.lightmaptexture = NULL;
10441                         rsurface.deluxemaptexture = NULL;
10442                         rsurface.uselightmaptexture = false;
10443                         for (;j < endsurface;j++)
10444                         {
10445                                 surface = rsurface.modelsurfaces + surfacelist[j];
10446                                 if (texture != surface->texture)
10447                                         break;
10448                                 texturesurfacelist[texturenumsurfaces++] = surface;
10449                         }
10450                 }
10451                 else
10452                 {
10453                         rsurface.lightmaptexture = surface->lightmaptexture;
10454                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10455                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10456                         for (;j < endsurface;j++)
10457                         {
10458                                 surface = rsurface.modelsurfaces + surfacelist[j];
10459                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10460                                         break;
10461                                 texturesurfacelist[texturenumsurfaces++] = surface;
10462                         }
10463                 }
10464                 // render the range of surfaces
10465                 if (ent == r_refdef.scene.worldentity)
10466                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10467                 else
10468                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10469         }
10470         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10471 }
10472
10473 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10474 {
10475         // transparent surfaces get pushed off into the transparent queue
10476         int surfacelistindex;
10477         const msurface_t *surface;
10478         vec3_t tempcenter, center;
10479         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10480         {
10481                 surface = texturesurfacelist[surfacelistindex];
10482                 if (r_transparent_sortsurfacesbynearest.integer)
10483                 {
10484                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10485                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10486                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10487                 }
10488                 else
10489                 {
10490                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10491                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10492                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10493                 }
10494                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10495                 if (rsurface.entity->transparent_offset) // transparent offset
10496                 {
10497                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10498                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10499                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10500                 }
10501                 R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10502         }
10503 }
10504
10505 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10506 {
10507         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10508                 return;
10509         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10510                 return;
10511         RSurf_SetupDepthAndCulling();
10512         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10513         if (rsurface.batchvertex3fbuffer)
10514                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10515         else
10516                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10517         RSurf_DrawBatch();
10518 }
10519
10520 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10521 {
10522         CHECKGLERROR
10523         if (depthonly)
10524                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10525         else if (prepass)
10526         {
10527                 if (!rsurface.texture->currentnumlayers)
10528                         return;
10529                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10530                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10531                 else
10532                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10533         }
10534         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10535                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10536         else if (!rsurface.texture->currentnumlayers)
10537                 return;
10538         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10539         {
10540                 // in the deferred case, transparent surfaces were queued during prepass
10541                 if (!r_shadow_usingdeferredprepass)
10542                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10543         }
10544         else
10545         {
10546                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10547                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10548         }
10549         CHECKGLERROR
10550 }
10551
10552 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10553 {
10554         int i, j;
10555         texture_t *texture;
10556         R_FrameData_SetMark();
10557         // break the surface list down into batches by texture and use of lightmapping
10558         for (i = 0;i < numsurfaces;i = j)
10559         {
10560                 j = i + 1;
10561                 // texture is the base texture pointer, rsurface.texture is the
10562                 // current frame/skin the texture is directing us to use (for example
10563                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10564                 // use skin 1 instead)
10565                 texture = surfacelist[i]->texture;
10566                 rsurface.texture = R_GetCurrentTexture(texture);
10567                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10568                 {
10569                         // if this texture is not the kind we want, skip ahead to the next one
10570                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10571                                 ;
10572                         continue;
10573                 }
10574                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10575                 {
10576                         rsurface.lightmaptexture = NULL;
10577                         rsurface.deluxemaptexture = NULL;
10578                         rsurface.uselightmaptexture = false;
10579                         // simply scan ahead until we find a different texture or lightmap state
10580                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10581                                 ;
10582                 }
10583                 else
10584                 {
10585                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10586                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10587                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10588                         // simply scan ahead until we find a different texture or lightmap state
10589                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10590                                 ;
10591                 }
10592                 // render the range of surfaces
10593                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10594         }
10595         R_FrameData_ReturnToMark();
10596 }
10597
10598 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10599 {
10600         CHECKGLERROR
10601         if (depthonly)
10602                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10603         else if (prepass)
10604         {
10605                 if (!rsurface.texture->currentnumlayers)
10606                         return;
10607                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10608                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10609                 else
10610                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10611         }
10612         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10613                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10614         else if (!rsurface.texture->currentnumlayers)
10615                 return;
10616         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10617         {
10618                 // in the deferred case, transparent surfaces were queued during prepass
10619                 if (!r_shadow_usingdeferredprepass)
10620                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10621         }
10622         else
10623         {
10624                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10625                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10626         }
10627         CHECKGLERROR
10628 }
10629
10630 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10631 {
10632         int i, j;
10633         texture_t *texture;
10634         R_FrameData_SetMark();
10635         // break the surface list down into batches by texture and use of lightmapping
10636         for (i = 0;i < numsurfaces;i = j)
10637         {
10638                 j = i + 1;
10639                 // texture is the base texture pointer, rsurface.texture is the
10640                 // current frame/skin the texture is directing us to use (for example
10641                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10642                 // use skin 1 instead)
10643                 texture = surfacelist[i]->texture;
10644                 rsurface.texture = R_GetCurrentTexture(texture);
10645                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10646                 {
10647                         // if this texture is not the kind we want, skip ahead to the next one
10648                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10649                                 ;
10650                         continue;
10651                 }
10652                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10653                 {
10654                         rsurface.lightmaptexture = NULL;
10655                         rsurface.deluxemaptexture = NULL;
10656                         rsurface.uselightmaptexture = false;
10657                         // simply scan ahead until we find a different texture or lightmap state
10658                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10659                                 ;
10660                 }
10661                 else
10662                 {
10663                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10664                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10665                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10666                         // simply scan ahead until we find a different texture or lightmap state
10667                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10668                                 ;
10669                 }
10670                 // render the range of surfaces
10671                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10672         }
10673         R_FrameData_ReturnToMark();
10674 }
10675
10676 float locboxvertex3f[6*4*3] =
10677 {
10678         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10679         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10680         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10681         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10682         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10683         1,0,0, 0,0,0, 0,1,0, 1,1,0
10684 };
10685
10686 unsigned short locboxelements[6*2*3] =
10687 {
10688          0, 1, 2, 0, 2, 3,
10689          4, 5, 6, 4, 6, 7,
10690          8, 9,10, 8,10,11,
10691         12,13,14, 12,14,15,
10692         16,17,18, 16,18,19,
10693         20,21,22, 20,22,23
10694 };
10695
10696 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10697 {
10698         int i, j;
10699         cl_locnode_t *loc = (cl_locnode_t *)ent;
10700         vec3_t mins, size;
10701         float vertex3f[6*4*3];
10702         CHECKGLERROR
10703         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10704         GL_DepthMask(false);
10705         GL_DepthRange(0, 1);
10706         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10707         GL_DepthTest(true);
10708         GL_CullFace(GL_NONE);
10709         R_EntityMatrix(&identitymatrix);
10710
10711 //      R_Mesh_ResetTextureState();
10712
10713         i = surfacelist[0];
10714         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10715                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10716                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10717                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10718
10719         if (VectorCompare(loc->mins, loc->maxs))
10720         {
10721                 VectorSet(size, 2, 2, 2);
10722                 VectorMA(loc->mins, -0.5f, size, mins);
10723         }
10724         else
10725         {
10726                 VectorCopy(loc->mins, mins);
10727                 VectorSubtract(loc->maxs, loc->mins, size);
10728         }
10729
10730         for (i = 0;i < 6*4*3;)
10731                 for (j = 0;j < 3;j++, i++)
10732                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10733
10734         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10735         R_SetupShader_Generic_NoTexture(false, false);
10736         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10737 }
10738
10739 void R_DrawLocs(void)
10740 {
10741         int index;
10742         cl_locnode_t *loc, *nearestloc;
10743         vec3_t center;
10744         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10745         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10746         {
10747                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10748                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10749         }
10750 }
10751
10752 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10753 {
10754         if (decalsystem->decals)
10755                 Mem_Free(decalsystem->decals);
10756         memset(decalsystem, 0, sizeof(*decalsystem));
10757 }
10758
10759 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)
10760 {
10761         tridecal_t *decal;
10762         tridecal_t *decals;
10763         int i;
10764
10765         // expand or initialize the system
10766         if (decalsystem->maxdecals <= decalsystem->numdecals)
10767         {
10768                 decalsystem_t old = *decalsystem;
10769                 qboolean useshortelements;
10770                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10771                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10772                 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)));
10773                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10774                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10775                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10776                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10777                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10778                 if (decalsystem->numdecals)
10779                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10780                 if (old.decals)
10781                         Mem_Free(old.decals);
10782                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10783                         decalsystem->element3i[i] = i;
10784                 if (useshortelements)
10785                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10786                                 decalsystem->element3s[i] = i;
10787         }
10788
10789         // grab a decal and search for another free slot for the next one
10790         decals = decalsystem->decals;
10791         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10792         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10793                 ;
10794         decalsystem->freedecal = i;
10795         if (decalsystem->numdecals <= i)
10796                 decalsystem->numdecals = i + 1;
10797
10798         // initialize the decal
10799         decal->lived = 0;
10800         decal->triangleindex = triangleindex;
10801         decal->surfaceindex = surfaceindex;
10802         decal->decalsequence = decalsequence;
10803         decal->color4f[0][0] = c0[0];
10804         decal->color4f[0][1] = c0[1];
10805         decal->color4f[0][2] = c0[2];
10806         decal->color4f[0][3] = 1;
10807         decal->color4f[1][0] = c1[0];
10808         decal->color4f[1][1] = c1[1];
10809         decal->color4f[1][2] = c1[2];
10810         decal->color4f[1][3] = 1;
10811         decal->color4f[2][0] = c2[0];
10812         decal->color4f[2][1] = c2[1];
10813         decal->color4f[2][2] = c2[2];
10814         decal->color4f[2][3] = 1;
10815         decal->vertex3f[0][0] = v0[0];
10816         decal->vertex3f[0][1] = v0[1];
10817         decal->vertex3f[0][2] = v0[2];
10818         decal->vertex3f[1][0] = v1[0];
10819         decal->vertex3f[1][1] = v1[1];
10820         decal->vertex3f[1][2] = v1[2];
10821         decal->vertex3f[2][0] = v2[0];
10822         decal->vertex3f[2][1] = v2[1];
10823         decal->vertex3f[2][2] = v2[2];
10824         decal->texcoord2f[0][0] = t0[0];
10825         decal->texcoord2f[0][1] = t0[1];
10826         decal->texcoord2f[1][0] = t1[0];
10827         decal->texcoord2f[1][1] = t1[1];
10828         decal->texcoord2f[2][0] = t2[0];
10829         decal->texcoord2f[2][1] = t2[1];
10830         TriangleNormal(v0, v1, v2, decal->plane);
10831         VectorNormalize(decal->plane);
10832         decal->plane[3] = DotProduct(v0, decal->plane);
10833 }
10834
10835 extern cvar_t cl_decals_bias;
10836 extern cvar_t cl_decals_models;
10837 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10838 // baseparms, parms, temps
10839 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)
10840 {
10841         int cornerindex;
10842         int index;
10843         float v[9][3];
10844         const float *vertex3f;
10845         const float *normal3f;
10846         int numpoints;
10847         float points[2][9][3];
10848         float temp[3];
10849         float tc[9][2];
10850         float f;
10851         float c[9][4];
10852         const int *e;
10853
10854         e = rsurface.modelelement3i + 3*triangleindex;
10855
10856         vertex3f = rsurface.modelvertex3f;
10857         normal3f = rsurface.modelnormal3f;
10858
10859         if (normal3f)
10860         {
10861                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10862                 {
10863                         index = 3*e[cornerindex];
10864                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10865                 }
10866         }
10867         else
10868         {
10869                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10870                 {
10871                         index = 3*e[cornerindex];
10872                         VectorCopy(vertex3f + index, v[cornerindex]);
10873                 }
10874         }
10875
10876         // cull backfaces
10877         //TriangleNormal(v[0], v[1], v[2], normal);
10878         //if (DotProduct(normal, localnormal) < 0.0f)
10879         //      continue;
10880         // clip by each of the box planes formed from the projection matrix
10881         // if anything survives, we emit the decal
10882         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]);
10883         if (numpoints < 3)
10884                 return;
10885         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]);
10886         if (numpoints < 3)
10887                 return;
10888         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]);
10889         if (numpoints < 3)
10890                 return;
10891         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]);
10892         if (numpoints < 3)
10893                 return;
10894         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]);
10895         if (numpoints < 3)
10896                 return;
10897         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]);
10898         if (numpoints < 3)
10899                 return;
10900         // some part of the triangle survived, so we have to accept it...
10901         if (dynamic)
10902         {
10903                 // dynamic always uses the original triangle
10904                 numpoints = 3;
10905                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10906                 {
10907                         index = 3*e[cornerindex];
10908                         VectorCopy(vertex3f + index, v[cornerindex]);
10909                 }
10910         }
10911         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10912         {
10913                 // convert vertex positions to texcoords
10914                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10915                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10916                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10917                 // calculate distance fade from the projection origin
10918                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10919                 f = bound(0.0f, f, 1.0f);
10920                 c[cornerindex][0] = r * f;
10921                 c[cornerindex][1] = g * f;
10922                 c[cornerindex][2] = b * f;
10923                 c[cornerindex][3] = 1.0f;
10924                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10925         }
10926         if (dynamic)
10927                 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);
10928         else
10929                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10930                         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);
10931 }
10932 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)
10933 {
10934         matrix4x4_t projection;
10935         decalsystem_t *decalsystem;
10936         qboolean dynamic;
10937         dp_model_t *model;
10938         const msurface_t *surface;
10939         const msurface_t *surfaces;
10940         const int *surfacelist;
10941         const texture_t *texture;
10942         int numtriangles;
10943         int numsurfacelist;
10944         int surfacelistindex;
10945         int surfaceindex;
10946         int triangleindex;
10947         float localorigin[3];
10948         float localnormal[3];
10949         float localmins[3];
10950         float localmaxs[3];
10951         float localsize;
10952         //float normal[3];
10953         float planes[6][4];
10954         float angles[3];
10955         bih_t *bih;
10956         int bih_triangles_count;
10957         int bih_triangles[256];
10958         int bih_surfaces[256];
10959
10960         decalsystem = &ent->decalsystem;
10961         model = ent->model;
10962         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10963         {
10964                 R_DecalSystem_Reset(&ent->decalsystem);
10965                 return;
10966         }
10967
10968         if (!model->brush.data_leafs && !cl_decals_models.integer)
10969         {
10970                 if (decalsystem->model)
10971                         R_DecalSystem_Reset(decalsystem);
10972                 return;
10973         }
10974
10975         if (decalsystem->model != model)
10976                 R_DecalSystem_Reset(decalsystem);
10977         decalsystem->model = model;
10978
10979         RSurf_ActiveModelEntity(ent, true, false, false);
10980
10981         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10982         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10983         VectorNormalize(localnormal);
10984         localsize = worldsize*rsurface.inversematrixscale;
10985         localmins[0] = localorigin[0] - localsize;
10986         localmins[1] = localorigin[1] - localsize;
10987         localmins[2] = localorigin[2] - localsize;
10988         localmaxs[0] = localorigin[0] + localsize;
10989         localmaxs[1] = localorigin[1] + localsize;
10990         localmaxs[2] = localorigin[2] + localsize;
10991
10992         //VectorCopy(localnormal, planes[4]);
10993         //VectorVectors(planes[4], planes[2], planes[0]);
10994         AnglesFromVectors(angles, localnormal, NULL, false);
10995         AngleVectors(angles, planes[0], planes[2], planes[4]);
10996         VectorNegate(planes[0], planes[1]);
10997         VectorNegate(planes[2], planes[3]);
10998         VectorNegate(planes[4], planes[5]);
10999         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11000         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11001         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11002         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11003         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11004         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11005
11006 #if 1
11007 // works
11008 {
11009         matrix4x4_t forwardprojection;
11010         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11011         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11012 }
11013 #else
11014 // broken
11015 {
11016         float projectionvector[4][3];
11017         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11018         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11019         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11020         projectionvector[0][0] = planes[0][0] * ilocalsize;
11021         projectionvector[0][1] = planes[1][0] * ilocalsize;
11022         projectionvector[0][2] = planes[2][0] * ilocalsize;
11023         projectionvector[1][0] = planes[0][1] * ilocalsize;
11024         projectionvector[1][1] = planes[1][1] * ilocalsize;
11025         projectionvector[1][2] = planes[2][1] * ilocalsize;
11026         projectionvector[2][0] = planes[0][2] * ilocalsize;
11027         projectionvector[2][1] = planes[1][2] * ilocalsize;
11028         projectionvector[2][2] = planes[2][2] * ilocalsize;
11029         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11030         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11031         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11032         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11033 }
11034 #endif
11035
11036         dynamic = model->surfmesh.isanimated;
11037         numsurfacelist = model->nummodelsurfaces;
11038         surfacelist = model->sortedmodelsurfaces;
11039         surfaces = model->data_surfaces;
11040
11041         bih = NULL;
11042         bih_triangles_count = -1;
11043         if(!dynamic)
11044         {
11045                 if(model->render_bih.numleafs)
11046                         bih = &model->render_bih;
11047                 else if(model->collision_bih.numleafs)
11048                         bih = &model->collision_bih;
11049         }
11050         if(bih)
11051                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11052         if(bih_triangles_count == 0)
11053                 return;
11054         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11055                 return;
11056         if(bih_triangles_count > 0)
11057         {
11058                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11059                 {
11060                         surfaceindex = bih_surfaces[triangleindex];
11061                         surface = surfaces + surfaceindex;
11062                         texture = surface->texture;
11063                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11064                                 continue;
11065                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11066                                 continue;
11067                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11068                 }
11069         }
11070         else
11071         {
11072                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11073                 {
11074                         surfaceindex = surfacelist[surfacelistindex];
11075                         surface = surfaces + surfaceindex;
11076                         // check cull box first because it rejects more than any other check
11077                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11078                                 continue;
11079                         // skip transparent surfaces
11080                         texture = surface->texture;
11081                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11082                                 continue;
11083                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11084                                 continue;
11085                         numtriangles = surface->num_triangles;
11086                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11087                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11088                 }
11089         }
11090 }
11091
11092 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11093 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)
11094 {
11095         int renderentityindex;
11096         float worldmins[3];
11097         float worldmaxs[3];
11098         entity_render_t *ent;
11099
11100         if (!cl_decals_newsystem.integer)
11101                 return;
11102
11103         worldmins[0] = worldorigin[0] - worldsize;
11104         worldmins[1] = worldorigin[1] - worldsize;
11105         worldmins[2] = worldorigin[2] - worldsize;
11106         worldmaxs[0] = worldorigin[0] + worldsize;
11107         worldmaxs[1] = worldorigin[1] + worldsize;
11108         worldmaxs[2] = worldorigin[2] + worldsize;
11109
11110         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11111
11112         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11113         {
11114                 ent = r_refdef.scene.entities[renderentityindex];
11115                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11116                         continue;
11117
11118                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11119         }
11120 }
11121
11122 typedef struct r_decalsystem_splatqueue_s
11123 {
11124         vec3_t worldorigin;
11125         vec3_t worldnormal;
11126         float color[4];
11127         float tcrange[4];
11128         float worldsize;
11129         int decalsequence;
11130 }
11131 r_decalsystem_splatqueue_t;
11132
11133 int r_decalsystem_numqueued = 0;
11134 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11135
11136 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)
11137 {
11138         r_decalsystem_splatqueue_t *queue;
11139
11140         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11141                 return;
11142
11143         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11144         VectorCopy(worldorigin, queue->worldorigin);
11145         VectorCopy(worldnormal, queue->worldnormal);
11146         Vector4Set(queue->color, r, g, b, a);
11147         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11148         queue->worldsize = worldsize;
11149         queue->decalsequence = cl.decalsequence++;
11150 }
11151
11152 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11153 {
11154         int i;
11155         r_decalsystem_splatqueue_t *queue;
11156
11157         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11158                 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);
11159         r_decalsystem_numqueued = 0;
11160 }
11161
11162 extern cvar_t cl_decals_max;
11163 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11164 {
11165         int i;
11166         decalsystem_t *decalsystem = &ent->decalsystem;
11167         int numdecals;
11168         int killsequence;
11169         tridecal_t *decal;
11170         float frametime;
11171         float lifetime;
11172
11173         if (!decalsystem->numdecals)
11174                 return;
11175
11176         if (r_showsurfaces.integer)
11177                 return;
11178
11179         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11180         {
11181                 R_DecalSystem_Reset(decalsystem);
11182                 return;
11183         }
11184
11185         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11186         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11187
11188         if (decalsystem->lastupdatetime)
11189                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11190         else
11191                 frametime = 0;
11192         decalsystem->lastupdatetime = r_refdef.scene.time;
11193         decal = decalsystem->decals;
11194         numdecals = decalsystem->numdecals;
11195
11196         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11197         {
11198                 if (decal->color4f[0][3])
11199                 {
11200                         decal->lived += frametime;
11201                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11202                         {
11203                                 memset(decal, 0, sizeof(*decal));
11204                                 if (decalsystem->freedecal > i)
11205                                         decalsystem->freedecal = i;
11206                         }
11207                 }
11208         }
11209         decal = decalsystem->decals;
11210         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11211                 numdecals--;
11212
11213         // collapse the array by shuffling the tail decals into the gaps
11214         for (;;)
11215         {
11216                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11217                         decalsystem->freedecal++;
11218                 if (decalsystem->freedecal == numdecals)
11219                         break;
11220                 decal[decalsystem->freedecal] = decal[--numdecals];
11221         }
11222
11223         decalsystem->numdecals = numdecals;
11224
11225         if (numdecals <= 0)
11226         {
11227                 // if there are no decals left, reset decalsystem
11228                 R_DecalSystem_Reset(decalsystem);
11229         }
11230 }
11231
11232 extern skinframe_t *decalskinframe;
11233 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11234 {
11235         int i;
11236         decalsystem_t *decalsystem = &ent->decalsystem;
11237         int numdecals;
11238         tridecal_t *decal;
11239         float faderate;
11240         float alpha;
11241         float *v3f;
11242         float *c4f;
11243         float *t2f;
11244         const int *e;
11245         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11246         int numtris = 0;
11247
11248         numdecals = decalsystem->numdecals;
11249         if (!numdecals)
11250                 return;
11251
11252         if (r_showsurfaces.integer)
11253                 return;
11254
11255         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11256         {
11257                 R_DecalSystem_Reset(decalsystem);
11258                 return;
11259         }
11260
11261         // if the model is static it doesn't matter what value we give for
11262         // wantnormals and wanttangents, so this logic uses only rules applicable
11263         // to a model, knowing that they are meaningless otherwise
11264         if (ent == r_refdef.scene.worldentity)
11265                 RSurf_ActiveWorldEntity();
11266         else
11267                 RSurf_ActiveModelEntity(ent, false, false, false);
11268
11269         decalsystem->lastupdatetime = r_refdef.scene.time;
11270         decal = decalsystem->decals;
11271
11272         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11273
11274         // update vertex positions for animated models
11275         v3f = decalsystem->vertex3f;
11276         c4f = decalsystem->color4f;
11277         t2f = decalsystem->texcoord2f;
11278         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11279         {
11280                 if (!decal->color4f[0][3])
11281                         continue;
11282
11283                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11284                         continue;
11285
11286                 // skip backfaces
11287                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11288                         continue;
11289
11290                 // update color values for fading decals
11291                 if (decal->lived >= cl_decals_time.value)
11292                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11293                 else
11294                         alpha = 1.0f;
11295
11296                 c4f[ 0] = decal->color4f[0][0] * alpha;
11297                 c4f[ 1] = decal->color4f[0][1] * alpha;
11298                 c4f[ 2] = decal->color4f[0][2] * alpha;
11299                 c4f[ 3] = 1;
11300                 c4f[ 4] = decal->color4f[1][0] * alpha;
11301                 c4f[ 5] = decal->color4f[1][1] * alpha;
11302                 c4f[ 6] = decal->color4f[1][2] * alpha;
11303                 c4f[ 7] = 1;
11304                 c4f[ 8] = decal->color4f[2][0] * alpha;
11305                 c4f[ 9] = decal->color4f[2][1] * alpha;
11306                 c4f[10] = decal->color4f[2][2] * alpha;
11307                 c4f[11] = 1;
11308
11309                 t2f[0] = decal->texcoord2f[0][0];
11310                 t2f[1] = decal->texcoord2f[0][1];
11311                 t2f[2] = decal->texcoord2f[1][0];
11312                 t2f[3] = decal->texcoord2f[1][1];
11313                 t2f[4] = decal->texcoord2f[2][0];
11314                 t2f[5] = decal->texcoord2f[2][1];
11315
11316                 // update vertex positions for animated models
11317                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11318                 {
11319                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11320                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11321                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11322                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11323                 }
11324                 else
11325                 {
11326                         VectorCopy(decal->vertex3f[0], v3f);
11327                         VectorCopy(decal->vertex3f[1], v3f + 3);
11328                         VectorCopy(decal->vertex3f[2], v3f + 6);
11329                 }
11330
11331                 if (r_refdef.fogenabled)
11332                 {
11333                         alpha = RSurf_FogVertex(v3f);
11334                         VectorScale(c4f, alpha, c4f);
11335                         alpha = RSurf_FogVertex(v3f + 3);
11336                         VectorScale(c4f + 4, alpha, c4f + 4);
11337                         alpha = RSurf_FogVertex(v3f + 6);
11338                         VectorScale(c4f + 8, alpha, c4f + 8);
11339                 }
11340
11341                 v3f += 9;
11342                 c4f += 12;
11343                 t2f += 6;
11344                 numtris++;
11345         }
11346
11347         if (numtris > 0)
11348         {
11349                 r_refdef.stats.drawndecals += numtris;
11350
11351                 // now render the decals all at once
11352                 // (this assumes they all use one particle font texture!)
11353                 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);
11354 //              R_Mesh_ResetTextureState();
11355                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11356                 GL_DepthMask(false);
11357                 GL_DepthRange(0, 1);
11358                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11359                 GL_DepthTest(true);
11360                 GL_CullFace(GL_NONE);
11361                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11362                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11363                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11364         }
11365 }
11366
11367 static void R_DrawModelDecals(void)
11368 {
11369         int i, numdecals;
11370
11371         // fade faster when there are too many decals
11372         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11373         for (i = 0;i < r_refdef.scene.numentities;i++)
11374                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11375
11376         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11377         for (i = 0;i < r_refdef.scene.numentities;i++)
11378                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11379                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11380
11381         R_DecalSystem_ApplySplatEntitiesQueue();
11382
11383         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11384         for (i = 0;i < r_refdef.scene.numentities;i++)
11385                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11386
11387         r_refdef.stats.totaldecals += numdecals;
11388
11389         if (r_showsurfaces.integer)
11390                 return;
11391
11392         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11393
11394         for (i = 0;i < r_refdef.scene.numentities;i++)
11395         {
11396                 if (!r_refdef.viewcache.entityvisible[i])
11397                         continue;
11398                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11399                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11400         }
11401 }
11402
11403 extern cvar_t mod_collision_bih;
11404 static void R_DrawDebugModel(void)
11405 {
11406         entity_render_t *ent = rsurface.entity;
11407         int i, j, k, l, flagsmask;
11408         const msurface_t *surface;
11409         dp_model_t *model = ent->model;
11410         vec3_t v;
11411
11412         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11413                 return;
11414
11415         if (r_showoverdraw.value > 0)
11416         {
11417                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11418                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11419                 R_SetupShader_Generic_NoTexture(false, false);
11420                 GL_DepthTest(false);
11421                 GL_DepthMask(false);
11422                 GL_DepthRange(0, 1);
11423                 GL_BlendFunc(GL_ONE, GL_ONE);
11424                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11425                 {
11426                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11427                                 continue;
11428                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11429                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11430                         {
11431                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11432                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11433                                 if (!rsurface.texture->currentlayers->depthmask)
11434                                         GL_Color(c, 0, 0, 1.0f);
11435                                 else if (ent == r_refdef.scene.worldentity)
11436                                         GL_Color(c, c, c, 1.0f);
11437                                 else
11438                                         GL_Color(0, c, 0, 1.0f);
11439                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11440                                 RSurf_DrawBatch();
11441                         }
11442                 }
11443                 rsurface.texture = NULL;
11444         }
11445
11446         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11447
11448 //      R_Mesh_ResetTextureState();
11449         R_SetupShader_Generic_NoTexture(false, false);
11450         GL_DepthRange(0, 1);
11451         GL_DepthTest(!r_showdisabledepthtest.integer);
11452         GL_DepthMask(false);
11453         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11454
11455         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11456         {
11457                 int triangleindex;
11458                 int bihleafindex;
11459                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11460                 const q3mbrush_t *brush;
11461                 const bih_t *bih = &model->collision_bih;
11462                 const bih_leaf_t *bihleaf;
11463                 float vertex3f[3][3];
11464                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11465                 cullbox = false;
11466                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11467                 {
11468                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11469                                 continue;
11470                         switch (bihleaf->type)
11471                         {
11472                         case BIH_BRUSH:
11473                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11474                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11475                                 {
11476                                         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);
11477                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11478                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11479                                 }
11480                                 break;
11481                         case BIH_COLLISIONTRIANGLE:
11482                                 triangleindex = bihleaf->itemindex;
11483                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11484                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11485                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11486                                 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);
11487                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11488                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11489                                 break;
11490                         case BIH_RENDERTRIANGLE:
11491                                 triangleindex = bihleaf->itemindex;
11492                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11493                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11494                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11495                                 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);
11496                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11497                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11498                                 break;
11499                         }
11500                 }
11501         }
11502
11503         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11504
11505 #ifndef USE_GLES2
11506         if (r_showtris.integer && qglPolygonMode)
11507         {
11508                 if (r_showdisabledepthtest.integer)
11509                 {
11510                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11511                         GL_DepthMask(false);
11512                 }
11513                 else
11514                 {
11515                         GL_BlendFunc(GL_ONE, GL_ZERO);
11516                         GL_DepthMask(true);
11517                 }
11518                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11519                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11520                 {
11521                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11522                                 continue;
11523                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11524                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11525                         {
11526                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11527                                 if (!rsurface.texture->currentlayers->depthmask)
11528                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11529                                 else if (ent == r_refdef.scene.worldentity)
11530                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11531                                 else
11532                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11533                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11534                                 RSurf_DrawBatch();
11535                         }
11536                 }
11537                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11538                 rsurface.texture = NULL;
11539         }
11540
11541         if (r_shownormals.value != 0 && qglBegin)
11542         {
11543                 if (r_showdisabledepthtest.integer)
11544                 {
11545                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11546                         GL_DepthMask(false);
11547                 }
11548                 else
11549                 {
11550                         GL_BlendFunc(GL_ONE, GL_ZERO);
11551                         GL_DepthMask(true);
11552                 }
11553                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11554                 {
11555                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11556                                 continue;
11557                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11558                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11559                         {
11560                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11561                                 qglBegin(GL_LINES);
11562                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11563                                 {
11564                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11565                                         {
11566                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11567                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11568                                                 qglVertex3f(v[0], v[1], v[2]);
11569                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11570                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11571                                                 qglVertex3f(v[0], v[1], v[2]);
11572                                         }
11573                                 }
11574                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11575                                 {
11576                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11577                                         {
11578                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11579                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11580                                                 qglVertex3f(v[0], v[1], v[2]);
11581                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11582                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11583                                                 qglVertex3f(v[0], v[1], v[2]);
11584                                         }
11585                                 }
11586                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11587                                 {
11588                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11589                                         {
11590                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11591                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11592                                                 qglVertex3f(v[0], v[1], v[2]);
11593                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11594                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11595                                                 qglVertex3f(v[0], v[1], v[2]);
11596                                         }
11597                                 }
11598                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11599                                 {
11600                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11601                                         {
11602                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11603                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11604                                                 qglVertex3f(v[0], v[1], v[2]);
11605                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11606                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11607                                                 qglVertex3f(v[0], v[1], v[2]);
11608                                         }
11609                                 }
11610                                 qglEnd();
11611                                 CHECKGLERROR
11612                         }
11613                 }
11614                 rsurface.texture = NULL;
11615         }
11616 #endif
11617 }
11618
11619 int r_maxsurfacelist = 0;
11620 const msurface_t **r_surfacelist = NULL;
11621 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11622 {
11623         int i, j, endj, flagsmask;
11624         dp_model_t *model = r_refdef.scene.worldmodel;
11625         msurface_t *surfaces;
11626         unsigned char *update;
11627         int numsurfacelist = 0;
11628         if (model == NULL)
11629                 return;
11630
11631         if (r_maxsurfacelist < model->num_surfaces)
11632         {
11633                 r_maxsurfacelist = model->num_surfaces;
11634                 if (r_surfacelist)
11635                         Mem_Free((msurface_t**)r_surfacelist);
11636                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11637         }
11638
11639         RSurf_ActiveWorldEntity();
11640
11641         surfaces = model->data_surfaces;
11642         update = model->brushq1.lightmapupdateflags;
11643
11644         // update light styles on this submodel
11645         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11646         {
11647                 model_brush_lightstyleinfo_t *style;
11648                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11649                 {
11650                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11651                         {
11652                                 int *list = style->surfacelist;
11653                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11654                                 for (j = 0;j < style->numsurfaces;j++)
11655                                         update[list[j]] = true;
11656                         }
11657                 }
11658         }
11659
11660         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11661
11662         if (debug)
11663         {
11664                 R_DrawDebugModel();
11665                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11666                 return;
11667         }
11668
11669         rsurface.lightmaptexture = NULL;
11670         rsurface.deluxemaptexture = NULL;
11671         rsurface.uselightmaptexture = false;
11672         rsurface.texture = NULL;
11673         rsurface.rtlight = NULL;
11674         numsurfacelist = 0;
11675         // add visible surfaces to draw list
11676         for (i = 0;i < model->nummodelsurfaces;i++)
11677         {
11678                 j = model->sortedmodelsurfaces[i];
11679                 if (r_refdef.viewcache.world_surfacevisible[j])
11680                         r_surfacelist[numsurfacelist++] = surfaces + j;
11681         }
11682         // update lightmaps if needed
11683         if (model->brushq1.firstrender)
11684         {
11685                 model->brushq1.firstrender = false;
11686                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11687                         if (update[j])
11688                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11689         }
11690         else if (update)
11691         {
11692                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11693                         if (r_refdef.viewcache.world_surfacevisible[j])
11694                                 if (update[j])
11695                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11696         }
11697         // don't do anything if there were no surfaces
11698         if (!numsurfacelist)
11699         {
11700                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11701                 return;
11702         }
11703         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11704
11705         // add to stats if desired
11706         if (r_speeds.integer && !skysurfaces && !depthonly)
11707         {
11708                 r_refdef.stats.world_surfaces += numsurfacelist;
11709                 for (j = 0;j < numsurfacelist;j++)
11710                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11711         }
11712
11713         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11714 }
11715
11716 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11717 {
11718         int i, j, endj, flagsmask;
11719         dp_model_t *model = ent->model;
11720         msurface_t *surfaces;
11721         unsigned char *update;
11722         int numsurfacelist = 0;
11723         if (model == NULL)
11724                 return;
11725
11726         if (r_maxsurfacelist < model->num_surfaces)
11727         {
11728                 r_maxsurfacelist = model->num_surfaces;
11729                 if (r_surfacelist)
11730                         Mem_Free((msurface_t **)r_surfacelist);
11731                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11732         }
11733
11734         // if the model is static it doesn't matter what value we give for
11735         // wantnormals and wanttangents, so this logic uses only rules applicable
11736         // to a model, knowing that they are meaningless otherwise
11737         if (ent == r_refdef.scene.worldentity)
11738                 RSurf_ActiveWorldEntity();
11739         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11740                 RSurf_ActiveModelEntity(ent, false, false, false);
11741         else if (prepass)
11742                 RSurf_ActiveModelEntity(ent, true, true, true);
11743         else if (depthonly)
11744         {
11745                 switch (vid.renderpath)
11746                 {
11747                 case RENDERPATH_GL20:
11748                 case RENDERPATH_D3D9:
11749                 case RENDERPATH_D3D10:
11750                 case RENDERPATH_D3D11:
11751                 case RENDERPATH_SOFT:
11752                 case RENDERPATH_GLES2:
11753                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11754                         break;
11755                 case RENDERPATH_GL11:
11756                 case RENDERPATH_GL13:
11757                 case RENDERPATH_GLES1:
11758                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11759                         break;
11760                 }
11761         }
11762         else
11763         {
11764                 switch (vid.renderpath)
11765                 {
11766                 case RENDERPATH_GL20:
11767                 case RENDERPATH_D3D9:
11768                 case RENDERPATH_D3D10:
11769                 case RENDERPATH_D3D11:
11770                 case RENDERPATH_SOFT:
11771                 case RENDERPATH_GLES2:
11772                         RSurf_ActiveModelEntity(ent, true, true, false);
11773                         break;
11774                 case RENDERPATH_GL11:
11775                 case RENDERPATH_GL13:
11776                 case RENDERPATH_GLES1:
11777                         RSurf_ActiveModelEntity(ent, true, false, false);
11778                         break;
11779                 }
11780         }
11781
11782         surfaces = model->data_surfaces;
11783         update = model->brushq1.lightmapupdateflags;
11784
11785         // update light styles
11786         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11787         {
11788                 model_brush_lightstyleinfo_t *style;
11789                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11790                 {
11791                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11792                         {
11793                                 int *list = style->surfacelist;
11794                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11795                                 for (j = 0;j < style->numsurfaces;j++)
11796                                         update[list[j]] = true;
11797                         }
11798                 }
11799         }
11800
11801         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11802
11803         if (debug)
11804         {
11805                 R_DrawDebugModel();
11806                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11807                 return;
11808         }
11809
11810         rsurface.lightmaptexture = NULL;
11811         rsurface.deluxemaptexture = NULL;
11812         rsurface.uselightmaptexture = false;
11813         rsurface.texture = NULL;
11814         rsurface.rtlight = NULL;
11815         numsurfacelist = 0;
11816         // add visible surfaces to draw list
11817         for (i = 0;i < model->nummodelsurfaces;i++)
11818                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11819         // don't do anything if there were no surfaces
11820         if (!numsurfacelist)
11821         {
11822                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11823                 return;
11824         }
11825         // update lightmaps if needed
11826         if (update)
11827         {
11828                 int updated = 0;
11829                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11830                 {
11831                         if (update[j])
11832                         {
11833                                 updated++;
11834                                 R_BuildLightMap(ent, surfaces + j);
11835                         }
11836                 }
11837         }
11838
11839         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11840
11841         // add to stats if desired
11842         if (r_speeds.integer && !skysurfaces && !depthonly)
11843         {
11844                 r_refdef.stats.entities_surfaces += numsurfacelist;
11845                 for (j = 0;j < numsurfacelist;j++)
11846                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11847         }
11848
11849         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11850 }
11851
11852 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11853 {
11854         static texture_t texture;
11855         static msurface_t surface;
11856         const msurface_t *surfacelist = &surface;
11857
11858         // fake enough texture and surface state to render this geometry
11859
11860         texture.update_lastrenderframe = -1; // regenerate this texture
11861         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11862         texture.currentskinframe = skinframe;
11863         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11864         texture.offsetmapping = OFFSETMAPPING_OFF;
11865         texture.offsetscale = 1;
11866         texture.specularscalemod = 1;
11867         texture.specularpowermod = 1;
11868
11869         surface.texture = &texture;
11870         surface.num_triangles = numtriangles;
11871         surface.num_firsttriangle = firsttriangle;
11872         surface.num_vertices = numvertices;
11873         surface.num_firstvertex = firstvertex;
11874
11875         // now render it
11876         rsurface.texture = R_GetCurrentTexture(surface.texture);
11877         rsurface.lightmaptexture = NULL;
11878         rsurface.deluxemaptexture = NULL;
11879         rsurface.uselightmaptexture = false;
11880         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11881 }
11882
11883 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)
11884 {
11885         static msurface_t surface;
11886         const msurface_t *surfacelist = &surface;
11887
11888         // fake enough texture and surface state to render this geometry
11889         surface.texture = texture;
11890         surface.num_triangles = numtriangles;
11891         surface.num_firsttriangle = firsttriangle;
11892         surface.num_vertices = numvertices;
11893         surface.num_firstvertex = firstvertex;
11894
11895         // now render it
11896         rsurface.texture = R_GetCurrentTexture(surface.texture);
11897         rsurface.lightmaptexture = NULL;
11898         rsurface.deluxemaptexture = NULL;
11899         rsurface.uselightmaptexture = false;
11900         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11901 }