]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
6d9147a7f56211804220e59c2228c48ea694d830
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
88 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
91 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
92 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
101 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
124 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
125 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"};
126 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"};
127 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
130 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
131 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
132 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"};
133 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
134 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
135 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 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
137 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
138
139 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
140 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
141 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
142 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
143 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
144 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
145 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
146 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
147
148 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)"};
149 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"};
150
151 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
152 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
153 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
154
155 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"};
156 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"};
157 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"};
158 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
159 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
160 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"};
161 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)"};
162 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)"};
163 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
164
165 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)"};
166 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
167 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)"};
168 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
169 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)"};
170 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)"};
171 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
172 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"};
173 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."};
174 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183
184 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)"};
185 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
186 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"};
187 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
188 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
189 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
190 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"};
191 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"};
192 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)"};
193
194 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
195 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
196 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
197 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
198
199 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
200 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
201
202 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
203 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
204 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
205 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
206 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
207 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
208
209 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
210 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
211 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
212 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
213 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
214 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
216 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
217 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
218 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
219
220 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"};
221
222 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"};
223
224 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
225
226 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
227
228 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
229 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"};
230
231 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
232
233 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)"};
234
235 extern cvar_t v_glslgamma;
236 extern cvar_t v_glslgamma_2d;
237
238 extern qboolean v_flipped_state;
239
240 r_framebufferstate_t r_fb;
241
242 /// shadow volume bsp struct with automatically growing nodes buffer
243 svbsp_t r_svbsp;
244
245 rtexture_t *r_texture_blanknormalmap;
246 rtexture_t *r_texture_white;
247 rtexture_t *r_texture_grey128;
248 rtexture_t *r_texture_black;
249 rtexture_t *r_texture_notexture;
250 rtexture_t *r_texture_whitecube;
251 rtexture_t *r_texture_normalizationcube;
252 rtexture_t *r_texture_fogattenuation;
253 rtexture_t *r_texture_fogheighttexture;
254 rtexture_t *r_texture_gammaramps;
255 unsigned int r_texture_gammaramps_serial;
256 //rtexture_t *r_texture_fogintensity;
257 rtexture_t *r_texture_reflectcube;
258
259 // TODO: hash lookups?
260 typedef struct cubemapinfo_s
261 {
262         char basename[64];
263         rtexture_t *texture;
264 }
265 cubemapinfo_t;
266
267 int r_texture_numcubemaps;
268 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
269
270 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
271 unsigned int r_numqueries;
272 unsigned int r_maxqueries;
273
274 typedef struct r_qwskincache_s
275 {
276         char name[MAX_QPATH];
277         skinframe_t *skinframe;
278 }
279 r_qwskincache_t;
280
281 static r_qwskincache_t *r_qwskincache;
282 static int r_qwskincache_size;
283
284 /// vertex coordinates for a quad that covers the screen exactly
285 extern const float r_screenvertex3f[12];
286 extern const float r_d3dscreenvertex3f[12];
287 const float r_screenvertex3f[12] =
288 {
289         0, 0, 0,
290         1, 0, 0,
291         1, 1, 0,
292         0, 1, 0
293 };
294 const float r_d3dscreenvertex3f[12] =
295 {
296         0, 1, 0,
297         1, 1, 0,
298         1, 0, 0,
299         0, 0, 0
300 };
301
302 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = in[0] * r;
308                 out[1] = in[1] * g;
309                 out[2] = in[2] * b;
310                 out[3] = in[3];
311                 in += 4;
312                 out += 4;
313         }
314 }
315
316 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
317 {
318         int i;
319         for (i = 0;i < verts;i++)
320         {
321                 out[0] = r;
322                 out[1] = g;
323                 out[2] = b;
324                 out[3] = a;
325                 out += 4;
326         }
327 }
328
329 // FIXME: move this to client?
330 void FOG_clear(void)
331 {
332         if (gamemode == GAME_NEHAHRA)
333         {
334                 Cvar_Set("gl_fogenable", "0");
335                 Cvar_Set("gl_fogdensity", "0.2");
336                 Cvar_Set("gl_fogred", "0.3");
337                 Cvar_Set("gl_foggreen", "0.3");
338                 Cvar_Set("gl_fogblue", "0.3");
339         }
340         r_refdef.fog_density = 0;
341         r_refdef.fog_red = 0;
342         r_refdef.fog_green = 0;
343         r_refdef.fog_blue = 0;
344         r_refdef.fog_alpha = 1;
345         r_refdef.fog_start = 0;
346         r_refdef.fog_end = 16384;
347         r_refdef.fog_height = 1<<30;
348         r_refdef.fog_fadedepth = 128;
349         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
350 }
351
352 static void R_BuildBlankTextures(void)
353 {
354         unsigned char data[4];
355         data[2] = 128; // normal X
356         data[1] = 128; // normal Y
357         data[0] = 255; // normal Z
358         data[3] = 255; // height
359         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 255;
361         data[1] = 255;
362         data[2] = 255;
363         data[3] = 255;
364         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 128;
366         data[1] = 128;
367         data[2] = 128;
368         data[3] = 255;
369         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 0;
371         data[1] = 0;
372         data[2] = 0;
373         data[3] = 255;
374         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375 }
376
377 static void R_BuildNoTexture(void)
378 {
379         int x, y;
380         unsigned char pix[16][16][4];
381         // this makes a light grey/dark grey checkerboard texture
382         for (y = 0;y < 16;y++)
383         {
384                 for (x = 0;x < 16;x++)
385                 {
386                         if ((y < 8) ^ (x < 8))
387                         {
388                                 pix[y][x][0] = 128;
389                                 pix[y][x][1] = 128;
390                                 pix[y][x][2] = 128;
391                                 pix[y][x][3] = 255;
392                         }
393                         else
394                         {
395                                 pix[y][x][0] = 64;
396                                 pix[y][x][1] = 64;
397                                 pix[y][x][2] = 64;
398                                 pix[y][x][3] = 255;
399                         }
400                 }
401         }
402         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildWhiteCube(void)
406 {
407         unsigned char data[6*1*1*4];
408         memset(data, 255, sizeof(data));
409         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
410 }
411
412 static void R_BuildNormalizationCube(void)
413 {
414         int x, y, side;
415         vec3_t v;
416         vec_t s, t, intensity;
417 #define NORMSIZE 64
418         unsigned char *data;
419         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
420         for (side = 0;side < 6;side++)
421         {
422                 for (y = 0;y < NORMSIZE;y++)
423                 {
424                         for (x = 0;x < NORMSIZE;x++)
425                         {
426                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
428                                 switch(side)
429                                 {
430                                 default:
431                                 case 0:
432                                         v[0] = 1;
433                                         v[1] = -t;
434                                         v[2] = -s;
435                                         break;
436                                 case 1:
437                                         v[0] = -1;
438                                         v[1] = -t;
439                                         v[2] = s;
440                                         break;
441                                 case 2:
442                                         v[0] = s;
443                                         v[1] = 1;
444                                         v[2] = t;
445                                         break;
446                                 case 3:
447                                         v[0] = s;
448                                         v[1] = -1;
449                                         v[2] = -t;
450                                         break;
451                                 case 4:
452                                         v[0] = s;
453                                         v[1] = -t;
454                                         v[2] = 1;
455                                         break;
456                                 case 5:
457                                         v[0] = -s;
458                                         v[1] = -t;
459                                         v[2] = -1;
460                                         break;
461                                 }
462                                 intensity = 127.0f / sqrt(DotProduct(v, v));
463                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
464                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
465                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
466                                 data[((side*64+y)*64+x)*4+3] = 255;
467                         }
468                 }
469         }
470         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
471         Mem_Free(data);
472 }
473
474 static void R_BuildFogTexture(void)
475 {
476         int x, b;
477 #define FOGWIDTH 256
478         unsigned char data1[FOGWIDTH][4];
479         //unsigned char data2[FOGWIDTH][4];
480         double d, r, alpha;
481
482         r_refdef.fogmasktable_start = r_refdef.fog_start;
483         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
484         r_refdef.fogmasktable_range = r_refdef.fogrange;
485         r_refdef.fogmasktable_density = r_refdef.fog_density;
486
487         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
488         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
489         {
490                 d = (x * r - r_refdef.fogmasktable_start);
491                 if(developer_extra.integer)
492                         Con_DPrintf("%f ", d);
493                 d = max(0, d);
494                 if (r_fog_exp2.integer)
495                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
496                 else
497                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
498                 if(developer_extra.integer)
499                         Con_DPrintf(" : %f ", alpha);
500                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
501                 if(developer_extra.integer)
502                         Con_DPrintf(" = %f\n", alpha);
503                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
504         }
505
506         for (x = 0;x < FOGWIDTH;x++)
507         {
508                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
509                 data1[x][0] = b;
510                 data1[x][1] = b;
511                 data1[x][2] = b;
512                 data1[x][3] = 255;
513                 //data2[x][0] = 255 - b;
514                 //data2[x][1] = 255 - b;
515                 //data2[x][2] = 255 - b;
516                 //data2[x][3] = 255;
517         }
518         if (r_texture_fogattenuation)
519         {
520                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
522         }
523         else
524         {
525                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
526                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
527         }
528 }
529
530 static void R_BuildFogHeightTexture(void)
531 {
532         unsigned char *inpixels;
533         int size;
534         int x;
535         int y;
536         int j;
537         float c[4];
538         float f;
539         inpixels = NULL;
540         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
541         if (r_refdef.fogheighttexturename[0])
542                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
543         if (!inpixels)
544         {
545                 r_refdef.fog_height_tablesize = 0;
546                 if (r_texture_fogheighttexture)
547                         R_FreeTexture(r_texture_fogheighttexture);
548                 r_texture_fogheighttexture = NULL;
549                 if (r_refdef.fog_height_table2d)
550                         Mem_Free(r_refdef.fog_height_table2d);
551                 r_refdef.fog_height_table2d = NULL;
552                 if (r_refdef.fog_height_table1d)
553                         Mem_Free(r_refdef.fog_height_table1d);
554                 r_refdef.fog_height_table1d = NULL;
555                 return;
556         }
557         size = image_width;
558         r_refdef.fog_height_tablesize = size;
559         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
560         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
561         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
562         Mem_Free(inpixels);
563         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
564         // average fog color table accounting for every fog layer between a point
565         // and the camera.  (Note: attenuation is handled separately!)
566         for (y = 0;y < size;y++)
567         {
568                 for (x = 0;x < size;x++)
569                 {
570                         Vector4Clear(c);
571                         f = 0;
572                         if (x < y)
573                         {
574                                 for (j = x;j <= y;j++)
575                                 {
576                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577                                         f++;
578                                 }
579                         }
580                         else
581                         {
582                                 for (j = x;j >= y;j--)
583                                 {
584                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
585                                         f++;
586                                 }
587                         }
588                         f = 1.0f / f;
589                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
591                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
592                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
593                 }
594         }
595         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
596 }
597
598 //=======================================================================================================================================================
599
600 static const char *builtinshaderstring =
601 #include "shader_glsl.h"
602 ;
603
604 const char *builtinhlslshaderstring =
605 #include "shader_hlsl.h"
606 ;
607
608 char *glslshaderstring = NULL;
609 char *hlslshaderstring = NULL;
610
611 //=======================================================================================================================================================
612
613 typedef struct shaderpermutationinfo_s
614 {
615         const char *pretext;
616         const char *name;
617 }
618 shaderpermutationinfo_t;
619
620 typedef struct shadermodeinfo_s
621 {
622         const char *vertexfilename;
623         const char *geometryfilename;
624         const char *fragmentfilename;
625         const char *pretext;
626         const char *name;
627 }
628 shadermodeinfo_t;
629
630 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
631 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
632 {
633         {"#define USEDIFFUSE\n", " diffuse"},
634         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
635         {"#define USEVIEWTINT\n", " viewtint"},
636         {"#define USECOLORMAPPING\n", " colormapping"},
637         {"#define USESATURATION\n", " saturation"},
638         {"#define USEFOGINSIDE\n", " foginside"},
639         {"#define USEFOGOUTSIDE\n", " fogoutside"},
640         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
641         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
642         {"#define USEGAMMARAMPS\n", " gammaramps"},
643         {"#define USECUBEFILTER\n", " cubefilter"},
644         {"#define USEGLOW\n", " glow"},
645         {"#define USEBLOOM\n", " bloom"},
646         {"#define USESPECULAR\n", " specular"},
647         {"#define USEPOSTPROCESSING\n", " postprocessing"},
648         {"#define USEREFLECTION\n", " reflection"},
649         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
650         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
651         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
652         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
653         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655         {"#define USEALPHAKILL\n", " alphakill"},
656         {"#define USEREFLECTCUBE\n", " reflectcube"},
657         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658         {"#define USEBOUNCEGRID\n", " bouncegrid"},
659         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
660         {"#define USETRIPPY\n", " trippy"},
661         {"#define USEDEPTHRGB\n", " depthrgb"},
662         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
663 };
664
665 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
666 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
667 {
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
686 };
687
688 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
689 {
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 };
709
710 struct r_glsl_permutation_s;
711 typedef struct r_glsl_permutation_s
712 {
713         /// hash lookup data
714         struct r_glsl_permutation_s *hashnext;
715         unsigned int mode;
716         unsigned int permutation;
717
718         /// indicates if we have tried compiling this permutation already
719         qboolean compiled;
720         /// 0 if compilation failed
721         int program;
722         // texture units assigned to each detected uniform
723         int tex_Texture_First;
724         int tex_Texture_Second;
725         int tex_Texture_GammaRamps;
726         int tex_Texture_Normal;
727         int tex_Texture_Color;
728         int tex_Texture_Gloss;
729         int tex_Texture_Glow;
730         int tex_Texture_SecondaryNormal;
731         int tex_Texture_SecondaryColor;
732         int tex_Texture_SecondaryGloss;
733         int tex_Texture_SecondaryGlow;
734         int tex_Texture_Pants;
735         int tex_Texture_Shirt;
736         int tex_Texture_FogHeightTexture;
737         int tex_Texture_FogMask;
738         int tex_Texture_Lightmap;
739         int tex_Texture_Deluxemap;
740         int tex_Texture_Attenuation;
741         int tex_Texture_Cube;
742         int tex_Texture_Refraction;
743         int tex_Texture_Reflection;
744         int tex_Texture_ShadowMap2D;
745         int tex_Texture_CubeProjection;
746         int tex_Texture_ScreenNormalMap;
747         int tex_Texture_ScreenDiffuse;
748         int tex_Texture_ScreenSpecular;
749         int tex_Texture_ReflectMask;
750         int tex_Texture_ReflectCube;
751         int tex_Texture_BounceGrid;
752         /// locations of detected uniforms in program object, or -1 if not found
753         int loc_Texture_First;
754         int loc_Texture_Second;
755         int loc_Texture_GammaRamps;
756         int loc_Texture_Normal;
757         int loc_Texture_Color;
758         int loc_Texture_Gloss;
759         int loc_Texture_Glow;
760         int loc_Texture_SecondaryNormal;
761         int loc_Texture_SecondaryColor;
762         int loc_Texture_SecondaryGloss;
763         int loc_Texture_SecondaryGlow;
764         int loc_Texture_Pants;
765         int loc_Texture_Shirt;
766         int loc_Texture_FogHeightTexture;
767         int loc_Texture_FogMask;
768         int loc_Texture_Lightmap;
769         int loc_Texture_Deluxemap;
770         int loc_Texture_Attenuation;
771         int loc_Texture_Cube;
772         int loc_Texture_Refraction;
773         int loc_Texture_Reflection;
774         int loc_Texture_ShadowMap2D;
775         int loc_Texture_CubeProjection;
776         int loc_Texture_ScreenNormalMap;
777         int loc_Texture_ScreenDiffuse;
778         int loc_Texture_ScreenSpecular;
779         int loc_Texture_ReflectMask;
780         int loc_Texture_ReflectCube;
781         int loc_Texture_BounceGrid;
782         int loc_Alpha;
783         int loc_BloomBlur_Parameters;
784         int loc_ClientTime;
785         int loc_Color_Ambient;
786         int loc_Color_Diffuse;
787         int loc_Color_Specular;
788         int loc_Color_Glow;
789         int loc_Color_Pants;
790         int loc_Color_Shirt;
791         int loc_DeferredColor_Ambient;
792         int loc_DeferredColor_Diffuse;
793         int loc_DeferredColor_Specular;
794         int loc_DeferredMod_Diffuse;
795         int loc_DeferredMod_Specular;
796         int loc_DistortScaleRefractReflect;
797         int loc_EyePosition;
798         int loc_FogColor;
799         int loc_FogHeightFade;
800         int loc_FogPlane;
801         int loc_FogPlaneViewDist;
802         int loc_FogRangeRecip;
803         int loc_LightColor;
804         int loc_LightDir;
805         int loc_LightPosition;
806         int loc_OffsetMapping_ScaleSteps;
807         int loc_OffsetMapping_LodDistance;
808         int loc_OffsetMapping_Bias;
809         int loc_PixelSize;
810         int loc_ReflectColor;
811         int loc_ReflectFactor;
812         int loc_ReflectOffset;
813         int loc_RefractColor;
814         int loc_Saturation;
815         int loc_ScreenCenterRefractReflect;
816         int loc_ScreenScaleRefractReflect;
817         int loc_ScreenToDepth;
818         int loc_ShadowMap_Parameters;
819         int loc_ShadowMap_TextureScale;
820         int loc_SpecularPower;
821         int loc_UserVec1;
822         int loc_UserVec2;
823         int loc_UserVec3;
824         int loc_UserVec4;
825         int loc_ViewTintColor;
826         int loc_ViewToLight;
827         int loc_ModelToLight;
828         int loc_TexMatrix;
829         int loc_BackgroundTexMatrix;
830         int loc_ModelViewProjectionMatrix;
831         int loc_ModelViewMatrix;
832         int loc_PixelToScreenTexCoord;
833         int loc_ModelToReflectCube;
834         int loc_ShadowMapMatrix;
835         int loc_BloomColorSubtract;
836         int loc_NormalmapScrollBlend;
837         int loc_BounceGridMatrix;
838         int loc_BounceGridIntensity;
839 }
840 r_glsl_permutation_t;
841
842 #define SHADERPERMUTATION_HASHSIZE 256
843
844
845 // non-degradable "lightweight" shader parameters to keep the permutations simpler
846 // these can NOT degrade! only use for simple stuff
847 enum
848 {
849         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
850         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
851         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
853         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
854         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
855         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
856         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
857         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
858         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
859         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
860         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
861         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
862 };
863 #define SHADERSTATICPARMS_COUNT 13
864
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
867
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870
871 extern qboolean r_shadow_shadowmapsampler;
872 extern int r_shadow_shadowmappcf;
873 qboolean R_CompileShader_CheckStaticParms(void)
874 {
875         static int r_compileshader_staticparms_save[1];
876         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
877         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
878
879         // detect all
880         if (r_glsl_saturation_redcompensate.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
882         if (r_glsl_vertextextureblend_usebothalphas.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
884         if (r_shadow_glossexact.integer)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
886         if (r_glsl_postprocess.integer)
887         {
888                 if (r_glsl_postprocess_uservec1_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
890                 if (r_glsl_postprocess_uservec2_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
892                 if (r_glsl_postprocess_uservec3_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
894                 if (r_glsl_postprocess_uservec4_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
896         }
897         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
898                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
899
900         if (r_shadow_shadowmapsampler)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
902         if (r_shadow_shadowmappcf > 1)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
904         else if (r_shadow_shadowmappcf)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
906         if (r_celshading.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
908         if (r_celoutlines.integer)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
910
911         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
912 }
913
914 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
915         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
916                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
917         else \
918                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
919 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
920 {
921         shaderstaticparms_count = 0;
922
923         // emit all
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
937 }
938
939 /// information about each possible shader permutation
940 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
941 /// currently selected permutation
942 r_glsl_permutation_t *r_glsl_permutation;
943 /// storage for permutations linked in the hash table
944 memexpandablearray_t r_glsl_permutationarray;
945
946 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
947 {
948         //unsigned int hashdepth = 0;
949         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
950         r_glsl_permutation_t *p;
951         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
952         {
953                 if (p->mode == mode && p->permutation == permutation)
954                 {
955                         //if (hashdepth > 10)
956                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957                         return p;
958                 }
959                 //hashdepth++;
960         }
961         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
962         p->mode = mode;
963         p->permutation = permutation;
964         p->hashnext = r_glsl_permutationhash[mode][hashindex];
965         r_glsl_permutationhash[mode][hashindex] = p;
966         //if (hashdepth > 10)
967         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
968         return p;
969 }
970
971 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
972 {
973         char *shaderstring;
974         if (!filename || !filename[0])
975                 return NULL;
976         if (!strcmp(filename, "glsl/default.glsl"))
977         {
978                 if (!glslshaderstring)
979                 {
980                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
981                         if (glslshaderstring)
982                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
983                         else
984                                 glslshaderstring = (char *)builtinshaderstring;
985                 }
986                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
987                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
988                 return shaderstring;
989         }
990         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
991         if (shaderstring)
992         {
993                 if (printfromdisknotice)
994                         Con_DPrintf("from disk %s... ", filename);
995                 return shaderstring;
996         }
997         return shaderstring;
998 }
999
1000 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1001 {
1002         int i;
1003         int sampler;
1004         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1005         char *vertexstring, *geometrystring, *fragmentstring;
1006         char permutationname[256];
1007         int vertstrings_count = 0;
1008         int geomstrings_count = 0;
1009         int fragstrings_count = 0;
1010         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1011         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1012         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1013
1014         if (p->compiled)
1015                 return;
1016         p->compiled = true;
1017         p->program = 0;
1018
1019         permutationname[0] = 0;
1020         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1021         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1022         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1023
1024         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1025
1026         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1027         if(vid.support.gl20shaders130)
1028         {
1029                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1030                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1031                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1032                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1033                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1034                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1035         }
1036
1037         // the first pretext is which type of shader to compile as
1038         // (later these will all be bound together as a program object)
1039         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1040         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1041         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1042
1043         // the second pretext is the mode (for example a light source)
1044         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1045         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1046         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1047         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1048
1049         // now add all the permutation pretexts
1050         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1051         {
1052                 if (permutation & (1<<i))
1053                 {
1054                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1056                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1057                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1058                 }
1059                 else
1060                 {
1061                         // keep line numbers correct
1062                         vertstrings_list[vertstrings_count++] = "\n";
1063                         geomstrings_list[geomstrings_count++] = "\n";
1064                         fragstrings_list[fragstrings_count++] = "\n";
1065                 }
1066         }
1067
1068         // add static parms
1069         R_CompileShader_AddStaticParms(mode, permutation);
1070         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         vertstrings_count += shaderstaticparms_count;
1072         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073         geomstrings_count += shaderstaticparms_count;
1074         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1075         fragstrings_count += shaderstaticparms_count;
1076
1077         // now append the shader text itself
1078         vertstrings_list[vertstrings_count++] = vertexstring;
1079         geomstrings_list[geomstrings_count++] = geometrystring;
1080         fragstrings_list[fragstrings_count++] = fragmentstring;
1081
1082         // if any sources were NULL, clear the respective list
1083         if (!vertexstring)
1084                 vertstrings_count = 0;
1085         if (!geometrystring)
1086                 geomstrings_count = 0;
1087         if (!fragmentstring)
1088                 fragstrings_count = 0;
1089
1090         // compile the shader program
1091         if (vertstrings_count + geomstrings_count + fragstrings_count)
1092                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1093         if (p->program)
1094         {
1095                 CHECKGLERROR
1096                 qglUseProgram(p->program);CHECKGLERROR
1097                 // look up all the uniform variable names we care about, so we don't
1098                 // have to look them up every time we set them
1099
1100                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1101                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1102                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1103                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1104                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1105                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1106                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1107                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1108                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1109                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1110                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1111                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1112                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1113                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1114                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1115                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1116                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1117                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1118                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1119                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1120                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1121                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1122                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1123                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1124                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1125                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1126                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1127                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1128                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1129                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1130                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1131                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1132                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1133                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1134                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1135                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1136                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1137                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1138                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1139                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1140                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1141                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1142                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1143                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1144                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1145                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1146                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1147                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1148                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1149                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1150                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1151                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1152                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1153                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1154                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1155                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1156                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1157                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1158                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1159                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1160                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1161                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1162                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1163                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1164                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1165                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1166                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1167                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1168                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1169                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1170                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1171                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1172                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1173                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1174                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1175                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1176                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1177                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1178                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1179                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1180                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1181                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1182                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1183                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1184                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1185                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1186                 // initialize the samplers to refer to the texture units we use
1187                 p->tex_Texture_First = -1;
1188                 p->tex_Texture_Second = -1;
1189                 p->tex_Texture_GammaRamps = -1;
1190                 p->tex_Texture_Normal = -1;
1191                 p->tex_Texture_Color = -1;
1192                 p->tex_Texture_Gloss = -1;
1193                 p->tex_Texture_Glow = -1;
1194                 p->tex_Texture_SecondaryNormal = -1;
1195                 p->tex_Texture_SecondaryColor = -1;
1196                 p->tex_Texture_SecondaryGloss = -1;
1197                 p->tex_Texture_SecondaryGlow = -1;
1198                 p->tex_Texture_Pants = -1;
1199                 p->tex_Texture_Shirt = -1;
1200                 p->tex_Texture_FogHeightTexture = -1;
1201                 p->tex_Texture_FogMask = -1;
1202                 p->tex_Texture_Lightmap = -1;
1203                 p->tex_Texture_Deluxemap = -1;
1204                 p->tex_Texture_Attenuation = -1;
1205                 p->tex_Texture_Cube = -1;
1206                 p->tex_Texture_Refraction = -1;
1207                 p->tex_Texture_Reflection = -1;
1208                 p->tex_Texture_ShadowMap2D = -1;
1209                 p->tex_Texture_CubeProjection = -1;
1210                 p->tex_Texture_ScreenNormalMap = -1;
1211                 p->tex_Texture_ScreenDiffuse = -1;
1212                 p->tex_Texture_ScreenSpecular = -1;
1213                 p->tex_Texture_ReflectMask = -1;
1214                 p->tex_Texture_ReflectCube = -1;
1215                 p->tex_Texture_BounceGrid = -1;
1216                 sampler = 0;
1217                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1218                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1219                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1220                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1221                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1222                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1223                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1227                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1228                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1229                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1230                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1231                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1232                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1233                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1234                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1235                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1236                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1237                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1238                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1239                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1242                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1243                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1244                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1245                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1246                 CHECKGLERROR
1247                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1248         }
1249         else
1250                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1251
1252         // free the strings
1253         if (vertexstring)
1254                 Mem_Free(vertexstring);
1255         if (geometrystring)
1256                 Mem_Free(geometrystring);
1257         if (fragmentstring)
1258                 Mem_Free(fragmentstring);
1259 }
1260
1261 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1262 {
1263         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1264         if (r_glsl_permutation != perm)
1265         {
1266                 r_glsl_permutation = perm;
1267                 if (!r_glsl_permutation->program)
1268                 {
1269                         if (!r_glsl_permutation->compiled)
1270                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1271                         if (!r_glsl_permutation->program)
1272                         {
1273                                 // remove features until we find a valid permutation
1274                                 int i;
1275                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1276                                 {
1277                                         // reduce i more quickly whenever it would not remove any bits
1278                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1279                                         if (!(permutation & j))
1280                                                 continue;
1281                                         permutation -= j;
1282                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1283                                         if (!r_glsl_permutation->compiled)
1284                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1285                                         if (r_glsl_permutation->program)
1286                                                 break;
1287                                 }
1288                                 if (i >= SHADERPERMUTATION_COUNT)
1289                                 {
1290                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1291                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1292                                         qglUseProgram(0);CHECKGLERROR
1293                                         return; // no bit left to clear, entire mode is broken
1294                                 }
1295                         }
1296                 }
1297                 CHECKGLERROR
1298                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1299         }
1300         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1301         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1302         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1303 }
1304
1305 #ifdef SUPPORTD3D
1306
1307 #ifdef SUPPORTD3D
1308 #include <d3d9.h>
1309 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1310 extern D3DCAPS9 vid_d3d9caps;
1311 #endif
1312
1313 struct r_hlsl_permutation_s;
1314 typedef struct r_hlsl_permutation_s
1315 {
1316         /// hash lookup data
1317         struct r_hlsl_permutation_s *hashnext;
1318         unsigned int mode;
1319         unsigned int permutation;
1320
1321         /// indicates if we have tried compiling this permutation already
1322         qboolean compiled;
1323         /// NULL if compilation failed
1324         IDirect3DVertexShader9 *vertexshader;
1325         IDirect3DPixelShader9 *pixelshader;
1326 }
1327 r_hlsl_permutation_t;
1328
1329 typedef enum D3DVSREGISTER_e
1330 {
1331         D3DVSREGISTER_TexMatrix = 0, // float4x4
1332         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1333         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1334         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1335         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1336         D3DVSREGISTER_ModelToLight = 20, // float4x4
1337         D3DVSREGISTER_EyePosition = 24,
1338         D3DVSREGISTER_FogPlane = 25,
1339         D3DVSREGISTER_LightDir = 26,
1340         D3DVSREGISTER_LightPosition = 27,
1341 }
1342 D3DVSREGISTER_t;
1343
1344 typedef enum D3DPSREGISTER_e
1345 {
1346         D3DPSREGISTER_Alpha = 0,
1347         D3DPSREGISTER_BloomBlur_Parameters = 1,
1348         D3DPSREGISTER_ClientTime = 2,
1349         D3DPSREGISTER_Color_Ambient = 3,
1350         D3DPSREGISTER_Color_Diffuse = 4,
1351         D3DPSREGISTER_Color_Specular = 5,
1352         D3DPSREGISTER_Color_Glow = 6,
1353         D3DPSREGISTER_Color_Pants = 7,
1354         D3DPSREGISTER_Color_Shirt = 8,
1355         D3DPSREGISTER_DeferredColor_Ambient = 9,
1356         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1357         D3DPSREGISTER_DeferredColor_Specular = 11,
1358         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1359         D3DPSREGISTER_DeferredMod_Specular = 13,
1360         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1361         D3DPSREGISTER_EyePosition = 15, // unused
1362         D3DPSREGISTER_FogColor = 16,
1363         D3DPSREGISTER_FogHeightFade = 17,
1364         D3DPSREGISTER_FogPlane = 18,
1365         D3DPSREGISTER_FogPlaneViewDist = 19,
1366         D3DPSREGISTER_FogRangeRecip = 20,
1367         D3DPSREGISTER_LightColor = 21,
1368         D3DPSREGISTER_LightDir = 22, // unused
1369         D3DPSREGISTER_LightPosition = 23,
1370         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1371         D3DPSREGISTER_PixelSize = 25,
1372         D3DPSREGISTER_ReflectColor = 26,
1373         D3DPSREGISTER_ReflectFactor = 27,
1374         D3DPSREGISTER_ReflectOffset = 28,
1375         D3DPSREGISTER_RefractColor = 29,
1376         D3DPSREGISTER_Saturation = 30,
1377         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1378         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1379         D3DPSREGISTER_ScreenToDepth = 33,
1380         D3DPSREGISTER_ShadowMap_Parameters = 34,
1381         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1382         D3DPSREGISTER_SpecularPower = 36,
1383         D3DPSREGISTER_UserVec1 = 37,
1384         D3DPSREGISTER_UserVec2 = 38,
1385         D3DPSREGISTER_UserVec3 = 39,
1386         D3DPSREGISTER_UserVec4 = 40,
1387         D3DPSREGISTER_ViewTintColor = 41,
1388         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1389         D3DPSREGISTER_BloomColorSubtract = 43,
1390         D3DPSREGISTER_ViewToLight = 44, // float4x4
1391         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1392         D3DPSREGISTER_NormalmapScrollBlend = 52,
1393         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1394         D3DPSREGISTER_OffsetMapping_Bias = 54,
1395         // next at 54
1396 }
1397 D3DPSREGISTER_t;
1398
1399 /// information about each possible shader permutation
1400 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1401 /// currently selected permutation
1402 r_hlsl_permutation_t *r_hlsl_permutation;
1403 /// storage for permutations linked in the hash table
1404 memexpandablearray_t r_hlsl_permutationarray;
1405
1406 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1407 {
1408         //unsigned int hashdepth = 0;
1409         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1410         r_hlsl_permutation_t *p;
1411         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1412         {
1413                 if (p->mode == mode && p->permutation == permutation)
1414                 {
1415                         //if (hashdepth > 10)
1416                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1417                         return p;
1418                 }
1419                 //hashdepth++;
1420         }
1421         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1422         p->mode = mode;
1423         p->permutation = permutation;
1424         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1425         r_hlsl_permutationhash[mode][hashindex] = p;
1426         //if (hashdepth > 10)
1427         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1428         return p;
1429 }
1430
1431 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1432 {
1433         char *shaderstring;
1434         if (!filename || !filename[0])
1435                 return NULL;
1436         if (!strcmp(filename, "hlsl/default.hlsl"))
1437         {
1438                 if (!hlslshaderstring)
1439                 {
1440                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441                         if (hlslshaderstring)
1442                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1443                         else
1444                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1445                 }
1446                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1447                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1448                 return shaderstring;
1449         }
1450         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1451         if (shaderstring)
1452         {
1453                 if (printfromdisknotice)
1454                         Con_DPrintf("from disk %s... ", filename);
1455                 return shaderstring;
1456         }
1457         return shaderstring;
1458 }
1459
1460 #include <d3dx9.h>
1461 //#include <d3dx9shader.h>
1462 //#include <d3dx9mesh.h>
1463
1464 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1465 {
1466         DWORD *vsbin = NULL;
1467         DWORD *psbin = NULL;
1468         fs_offset_t vsbinsize;
1469         fs_offset_t psbinsize;
1470 //      IDirect3DVertexShader9 *vs = NULL;
1471 //      IDirect3DPixelShader9 *ps = NULL;
1472         ID3DXBuffer *vslog = NULL;
1473         ID3DXBuffer *vsbuffer = NULL;
1474         ID3DXConstantTable *vsconstanttable = NULL;
1475         ID3DXBuffer *pslog = NULL;
1476         ID3DXBuffer *psbuffer = NULL;
1477         ID3DXConstantTable *psconstanttable = NULL;
1478         int vsresult = 0;
1479         int psresult = 0;
1480         char temp[MAX_INPUTLINE];
1481         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1482         char vabuf[1024];
1483         qboolean debugshader = gl_paranoid.integer != 0;
1484         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1486         if (!debugshader)
1487         {
1488                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1489                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1490         }
1491         if ((!vsbin && vertstring) || (!psbin && fragstring))
1492         {
1493                 const char* dllnames_d3dx9 [] =
1494                 {
1495                         "d3dx9_43.dll",
1496                         "d3dx9_42.dll",
1497                         "d3dx9_41.dll",
1498                         "d3dx9_40.dll",
1499                         "d3dx9_39.dll",
1500                         "d3dx9_38.dll",
1501                         "d3dx9_37.dll",
1502                         "d3dx9_36.dll",
1503                         "d3dx9_35.dll",
1504                         "d3dx9_34.dll",
1505                         "d3dx9_33.dll",
1506                         "d3dx9_32.dll",
1507                         "d3dx9_31.dll",
1508                         "d3dx9_30.dll",
1509                         "d3dx9_29.dll",
1510                         "d3dx9_28.dll",
1511                         "d3dx9_27.dll",
1512                         "d3dx9_26.dll",
1513                         "d3dx9_25.dll",
1514                         "d3dx9_24.dll",
1515                         NULL
1516                 };
1517                 dllhandle_t d3dx9_dll = NULL;
1518                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1519                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1520                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1521                 dllfunction_t d3dx9_dllfuncs[] =
1522                 {
1523                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1524                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1525                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1526                         {NULL, NULL}
1527                 };
1528                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1529                 {
1530                         DWORD shaderflags = 0;
1531                         if (debugshader)
1532                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1533                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1534                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1535                         if (vertstring && vertstring[0])
1536                         {
1537                                 if (debugshader)
1538                                 {
1539                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1540                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1541                                 }
1542                                 else
1543                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544                                 if (vsbuffer)
1545                                 {
1546                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1547                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1548                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1549                                         ID3DXBuffer_Release(vsbuffer);
1550                                 }
1551                                 if (vslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1554                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         ID3DXBuffer_Release(vslog);
1556                                 }
1557                         }
1558                         if (fragstring && fragstring[0])
1559                         {
1560                                 if (debugshader)
1561                                 {
1562                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1563                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1564                                 }
1565                                 else
1566                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567                                 if (psbuffer)
1568                                 {
1569                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1570                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1571                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1572                                         ID3DXBuffer_Release(psbuffer);
1573                                 }
1574                                 if (pslog)
1575                                 {
1576                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1577                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1578                                         ID3DXBuffer_Release(pslog);
1579                                 }
1580                         }
1581                         Sys_UnloadLibrary(&d3dx9_dll);
1582                 }
1583                 else
1584                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1585         }
1586         if (vsbin && psbin)
1587         {
1588                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1589                 if (FAILED(vsresult))
1590                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1591                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1592                 if (FAILED(psresult))
1593                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1594         }
1595         // free the shader data
1596         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1597         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1598 }
1599
1600 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1601 {
1602         int i;
1603         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1604         int vertstring_length = 0;
1605         int geomstring_length = 0;
1606         int fragstring_length = 0;
1607         char *t;
1608         char *vertexstring, *geometrystring, *fragmentstring;
1609         char *vertstring, *geomstring, *fragstring;
1610         char permutationname[256];
1611         char cachename[256];
1612         int vertstrings_count = 0;
1613         int geomstrings_count = 0;
1614         int fragstrings_count = 0;
1615         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1616         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1617         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1618
1619         if (p->compiled)
1620                 return;
1621         p->compiled = true;
1622         p->vertexshader = NULL;
1623         p->pixelshader = NULL;
1624
1625         permutationname[0] = 0;
1626         cachename[0] = 0;
1627         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1628         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1629         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1630
1631         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1632         strlcat(cachename, "hlsl/", sizeof(cachename));
1633
1634         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1635         vertstrings_count = 0;
1636         geomstrings_count = 0;
1637         fragstrings_count = 0;
1638         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1639         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1640         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1641
1642         // the first pretext is which type of shader to compile as
1643         // (later these will all be bound together as a program object)
1644         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1645         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1646         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1647
1648         // the second pretext is the mode (for example a light source)
1649         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1650         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1651         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1652         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1653         strlcat(cachename, modeinfo->name, sizeof(cachename));
1654
1655         // now add all the permutation pretexts
1656         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1657         {
1658                 if (permutation & (1<<i))
1659                 {
1660                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1661                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1662                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1663                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1664                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1665                 }
1666                 else
1667                 {
1668                         // keep line numbers correct
1669                         vertstrings_list[vertstrings_count++] = "\n";
1670                         geomstrings_list[geomstrings_count++] = "\n";
1671                         fragstrings_list[fragstrings_count++] = "\n";
1672                 }
1673         }
1674
1675         // add static parms
1676         R_CompileShader_AddStaticParms(mode, permutation);
1677         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1678         vertstrings_count += shaderstaticparms_count;
1679         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1680         geomstrings_count += shaderstaticparms_count;
1681         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682         fragstrings_count += shaderstaticparms_count;
1683
1684         // replace spaces in the cachename with _ characters
1685         for (i = 0;cachename[i];i++)
1686                 if (cachename[i] == ' ')
1687                         cachename[i] = '_';
1688
1689         // now append the shader text itself
1690         vertstrings_list[vertstrings_count++] = vertexstring;
1691         geomstrings_list[geomstrings_count++] = geometrystring;
1692         fragstrings_list[fragstrings_count++] = fragmentstring;
1693
1694         // if any sources were NULL, clear the respective list
1695         if (!vertexstring)
1696                 vertstrings_count = 0;
1697         if (!geometrystring)
1698                 geomstrings_count = 0;
1699         if (!fragmentstring)
1700                 fragstrings_count = 0;
1701
1702         vertstring_length = 0;
1703         for (i = 0;i < vertstrings_count;i++)
1704                 vertstring_length += strlen(vertstrings_list[i]);
1705         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1706         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1707                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1708
1709         geomstring_length = 0;
1710         for (i = 0;i < geomstrings_count;i++)
1711                 geomstring_length += strlen(geomstrings_list[i]);
1712         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1713         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1714                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1715
1716         fragstring_length = 0;
1717         for (i = 0;i < fragstrings_count;i++)
1718                 fragstring_length += strlen(fragstrings_list[i]);
1719         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1720         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1721                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1722
1723         // try to load the cached shader, or generate one
1724         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1725
1726         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1727                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1728         else
1729                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1730
1731         // free the strings
1732         if (vertstring)
1733                 Mem_Free(vertstring);
1734         if (geomstring)
1735                 Mem_Free(geomstring);
1736         if (fragstring)
1737                 Mem_Free(fragstring);
1738         if (vertexstring)
1739                 Mem_Free(vertexstring);
1740         if (geometrystring)
1741                 Mem_Free(geometrystring);
1742         if (fragmentstring)
1743                 Mem_Free(fragmentstring);
1744 }
1745
1746 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1747 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1748 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);}
1749 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);}
1750 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);}
1751 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);}
1752
1753 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1754 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1755 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);}
1756 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);}
1757 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);}
1758 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);}
1759
1760 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1761 {
1762         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1763         if (r_hlsl_permutation != perm)
1764         {
1765                 r_hlsl_permutation = perm;
1766                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1767                 {
1768                         if (!r_hlsl_permutation->compiled)
1769                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1770                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1771                         {
1772                                 // remove features until we find a valid permutation
1773                                 int i;
1774                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1775                                 {
1776                                         // reduce i more quickly whenever it would not remove any bits
1777                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1778                                         if (!(permutation & j))
1779                                                 continue;
1780                                         permutation -= j;
1781                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782                                         if (!r_hlsl_permutation->compiled)
1783                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1784                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1785                                                 break;
1786                                 }
1787                                 if (i >= SHADERPERMUTATION_COUNT)
1788                                 {
1789                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1790                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1791                                         return; // no bit left to clear, entire mode is broken
1792                                 }
1793                         }
1794                 }
1795                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1796                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1797         }
1798         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1799         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1800         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1801 }
1802 #endif
1803
1804 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1805 {
1806         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1807         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1808         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1809         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1810 }
1811
1812 void R_GLSL_Restart_f(void)
1813 {
1814         unsigned int i, limit;
1815         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1816                 Mem_Free(glslshaderstring);
1817         glslshaderstring = NULL;
1818         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1819                 Mem_Free(hlslshaderstring);
1820         hlslshaderstring = NULL;
1821         switch(vid.renderpath)
1822         {
1823         case RENDERPATH_D3D9:
1824 #ifdef SUPPORTD3D
1825                 {
1826                         r_hlsl_permutation_t *p;
1827                         r_hlsl_permutation = NULL;
1828                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1829                         for (i = 0;i < limit;i++)
1830                         {
1831                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1832                                 {
1833                                         if (p->vertexshader)
1834                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1835                                         if (p->pixelshader)
1836                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1837                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1838                                 }
1839                         }
1840                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1841                 }
1842 #endif
1843                 break;
1844         case RENDERPATH_D3D10:
1845                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1846                 break;
1847         case RENDERPATH_D3D11:
1848                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1849                 break;
1850         case RENDERPATH_GL20:
1851         case RENDERPATH_GLES2:
1852                 {
1853                         r_glsl_permutation_t *p;
1854                         r_glsl_permutation = NULL;
1855                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1856                         for (i = 0;i < limit;i++)
1857                         {
1858                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1859                                 {
1860                                         GL_Backend_FreeProgram(p->program);
1861                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1862                                 }
1863                         }
1864                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1865                 }
1866                 break;
1867         case RENDERPATH_GL11:
1868         case RENDERPATH_GL13:
1869         case RENDERPATH_GLES1:
1870                 break;
1871         case RENDERPATH_SOFT:
1872                 break;
1873         }
1874 }
1875
1876 static void R_GLSL_DumpShader_f(void)
1877 {
1878         int i;
1879         qfile_t *file;
1880
1881         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1882         if (file)
1883         {
1884                 FS_Print(file, "/* The engine may define the following macros:\n");
1885                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1886                 for (i = 0;i < SHADERMODE_COUNT;i++)
1887                         FS_Print(file, glslshadermodeinfo[i].pretext);
1888                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1889                         FS_Print(file, shaderpermutationinfo[i].pretext);
1890                 FS_Print(file, "*/\n");
1891                 FS_Print(file, builtinshaderstring);
1892                 FS_Close(file);
1893                 Con_Printf("glsl/default.glsl written\n");
1894         }
1895         else
1896                 Con_Printf("failed to write to glsl/default.glsl\n");
1897
1898         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1899         if (file)
1900         {
1901                 FS_Print(file, "/* The engine may define the following macros:\n");
1902                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1903                 for (i = 0;i < SHADERMODE_COUNT;i++)
1904                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1905                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1906                         FS_Print(file, shaderpermutationinfo[i].pretext);
1907                 FS_Print(file, "*/\n");
1908                 FS_Print(file, builtinhlslshaderstring);
1909                 FS_Close(file);
1910                 Con_Printf("hlsl/default.hlsl written\n");
1911         }
1912         else
1913                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1914 }
1915
1916 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1917 {
1918         unsigned int permutation = 0;
1919         if (r_trippy.integer && !notrippy)
1920                 permutation |= SHADERPERMUTATION_TRIPPY;
1921         permutation |= SHADERPERMUTATION_VIEWTINT;
1922         if (first)
1923                 permutation |= SHADERPERMUTATION_DIFFUSE;
1924         if (second)
1925                 permutation |= SHADERPERMUTATION_SPECULAR;
1926         if (texturemode == GL_MODULATE)
1927                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1928         else if (texturemode == GL_ADD)
1929                 permutation |= SHADERPERMUTATION_GLOW;
1930         else if (texturemode == GL_DECAL)
1931                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1932         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1933                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1934         if (suppresstexalpha)
1935                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1936         if (!second)
1937                 texturemode = GL_MODULATE;
1938         if (vid.allowalphatocoverage)
1939                 GL_AlphaToCoverage(false);
1940         switch (vid.renderpath)
1941         {
1942         case RENDERPATH_D3D9:
1943 #ifdef SUPPORTD3D
1944                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1945                 R_Mesh_TexBind(GL20TU_FIRST , first );
1946                 R_Mesh_TexBind(GL20TU_SECOND, second);
1947                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1948                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1949 #endif
1950                 break;
1951         case RENDERPATH_D3D10:
1952                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953                 break;
1954         case RENDERPATH_D3D11:
1955                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_GL20:
1958         case RENDERPATH_GLES2:
1959                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1960                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1961                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1962                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1963                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1964                 break;
1965         case RENDERPATH_GL13:
1966         case RENDERPATH_GLES1:
1967                 R_Mesh_TexBind(0, first );
1968                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1969                 R_Mesh_TexBind(1, second);
1970                 if (second)
1971                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1972                 break;
1973         case RENDERPATH_GL11:
1974                 R_Mesh_TexBind(0, first );
1975                 break;
1976         case RENDERPATH_SOFT:
1977                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1978                 R_Mesh_TexBind(GL20TU_FIRST , first );
1979                 R_Mesh_TexBind(GL20TU_SECOND, second);
1980                 break;
1981         }
1982 }
1983
1984 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1985 {
1986         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1987 }
1988
1989 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1990 {
1991         unsigned int permutation = 0;
1992         if (r_trippy.integer && !notrippy)
1993                 permutation |= SHADERPERMUTATION_TRIPPY;
1994         if (depthrgb)
1995                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1996         if (vid.allowalphatocoverage)
1997                 GL_AlphaToCoverage(false);
1998         switch (vid.renderpath)
1999         {
2000         case RENDERPATH_D3D9:
2001 #ifdef SUPPORTD3D
2002                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2003 #endif
2004                 break;
2005         case RENDERPATH_D3D10:
2006                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2007                 break;
2008         case RENDERPATH_D3D11:
2009                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2010                 break;
2011         case RENDERPATH_GL20:
2012         case RENDERPATH_GLES2:
2013                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2014                 break;
2015         case RENDERPATH_GL13:
2016         case RENDERPATH_GLES1:
2017                 R_Mesh_TexBind(0, 0);
2018                 R_Mesh_TexBind(1, 0);
2019                 break;
2020         case RENDERPATH_GL11:
2021                 R_Mesh_TexBind(0, 0);
2022                 break;
2023         case RENDERPATH_SOFT:
2024                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2025                 break;
2026         }
2027 }
2028
2029 void R_SetupShader_ShowDepth(qboolean notrippy)
2030 {
2031         int permutation = 0;
2032         if (r_trippy.integer && !notrippy)
2033                 permutation |= SHADERPERMUTATION_TRIPPY;
2034         if (vid.allowalphatocoverage)
2035                 GL_AlphaToCoverage(false);
2036         switch (vid.renderpath)
2037         {
2038         case RENDERPATH_D3D9:
2039 #ifdef SUPPORTHLSL
2040                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2041 #endif
2042                 break;
2043         case RENDERPATH_D3D10:
2044                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2045                 break;
2046         case RENDERPATH_D3D11:
2047                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2048                 break;
2049         case RENDERPATH_GL20:
2050         case RENDERPATH_GLES2:
2051                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2052                 break;
2053         case RENDERPATH_GL13:
2054         case RENDERPATH_GLES1:
2055                 break;
2056         case RENDERPATH_GL11:
2057                 break;
2058         case RENDERPATH_SOFT:
2059                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2060                 break;
2061         }
2062 }
2063
2064 extern qboolean r_shadow_usingdeferredprepass;
2065 extern rtexture_t *r_shadow_attenuationgradienttexture;
2066 extern rtexture_t *r_shadow_attenuation2dtexture;
2067 extern rtexture_t *r_shadow_attenuation3dtexture;
2068 extern qboolean r_shadow_usingshadowmap2d;
2069 extern qboolean r_shadow_usingshadowmaportho;
2070 extern float r_shadow_shadowmap_texturescale[2];
2071 extern float r_shadow_shadowmap_parameters[4];
2072 extern qboolean r_shadow_shadowmapvsdct;
2073 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2074 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2075 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2076 extern matrix4x4_t r_shadow_shadowmapmatrix;
2077 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2078 extern int r_shadow_prepass_width;
2079 extern int r_shadow_prepass_height;
2080 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2081 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2082 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2083 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2084
2085 #define BLENDFUNC_ALLOWS_COLORMOD      1
2086 #define BLENDFUNC_ALLOWS_FOG           2
2087 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2088 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2089 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2090 static int R_BlendFuncFlags(int src, int dst)
2091 {
2092         int r = 0;
2093
2094         // a blendfunc allows colormod if:
2095         // a) it can never keep the destination pixel invariant, or
2096         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2097         // this is to prevent unintended side effects from colormod
2098
2099         // a blendfunc allows fog if:
2100         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2101         // this is to prevent unintended side effects from fog
2102
2103         // these checks are the output of fogeval.pl
2104
2105         r |= BLENDFUNC_ALLOWS_COLORMOD;
2106         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2107         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2115         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2116         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2124         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2125         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2126         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2127
2128         return r;
2129 }
2130
2131 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)
2132 {
2133         // select a permutation of the lighting shader appropriate to this
2134         // combination of texture, entity, light source, and fogging, only use the
2135         // minimum features necessary to avoid wasting rendering time in the
2136         // fragment shader on features that are not being used
2137         unsigned int permutation = 0;
2138         unsigned int mode = 0;
2139         int blendfuncflags;
2140         static float dummy_colormod[3] = {1, 1, 1};
2141         float *colormod = rsurface.colormod;
2142         float m16f[16];
2143         matrix4x4_t tempmatrix;
2144         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2145         if (r_trippy.integer && !notrippy)
2146                 permutation |= SHADERPERMUTATION_TRIPPY;
2147         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2148                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2149         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2150                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2151         if (rsurfacepass == RSURFPASS_BACKGROUND)
2152         {
2153                 // distorted background
2154                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2155                 {
2156                         mode = SHADERMODE_WATER;
2157                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2158                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2159                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2160                         {
2161                                 // this is the right thing to do for wateralpha
2162                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2163                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2164                         }
2165                         else
2166                         {
2167                                 // this is the right thing to do for entity alpha
2168                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2169                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170                         }
2171                 }
2172                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2173                 {
2174                         mode = SHADERMODE_REFRACTION;
2175                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2176                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2177                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2178                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2179                 }
2180                 else
2181                 {
2182                         mode = SHADERMODE_GENERIC;
2183                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2184                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2185                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2186                 }
2187                 if (vid.allowalphatocoverage)
2188                         GL_AlphaToCoverage(false);
2189         }
2190         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2191         {
2192                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2193                 {
2194                         switch(rsurface.texture->offsetmapping)
2195                         {
2196                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2197                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2198                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2199                         case OFFSETMAPPING_OFF: break;
2200                         }
2201                 }
2202                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2203                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2204                 // normalmap (deferred prepass), may use alpha test on diffuse
2205                 mode = SHADERMODE_DEFERREDGEOMETRY;
2206                 GL_BlendFunc(GL_ONE, GL_ZERO);
2207                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2208                 if (vid.allowalphatocoverage)
2209                         GL_AlphaToCoverage(false);
2210         }
2211         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2212         {
2213                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2214                 {
2215                         switch(rsurface.texture->offsetmapping)
2216                         {
2217                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2218                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2219                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2220                         case OFFSETMAPPING_OFF: break;
2221                         }
2222                 }
2223                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2224                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2225                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2226                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2227                 // light source
2228                 mode = SHADERMODE_LIGHTSOURCE;
2229                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2230                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2231                 if (diffusescale > 0)
2232                         permutation |= SHADERPERMUTATION_DIFFUSE;
2233                 if (specularscale > 0)
2234                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2235                 if (r_refdef.fogenabled)
2236                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2237                 if (rsurface.texture->colormapping)
2238                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2239                 if (r_shadow_usingshadowmap2d)
2240                 {
2241                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2242                         if(r_shadow_shadowmapvsdct)
2243                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2244
2245                         if (r_shadow_shadowmap2ddepthbuffer)
2246                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2247                 }
2248                 if (rsurface.texture->reflectmasktexture)
2249                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2250                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2251                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2252                 if (vid.allowalphatocoverage)
2253                         GL_AlphaToCoverage(false);
2254         }
2255         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2256         {
2257                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2258                 {
2259                         switch(rsurface.texture->offsetmapping)
2260                         {
2261                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2262                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2263                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2264                         case OFFSETMAPPING_OFF: break;
2265                         }
2266                 }
2267                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2268                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2270                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2271                 // unshaded geometry (fullbright or ambient model lighting)
2272                 mode = SHADERMODE_FLATCOLOR;
2273                 ambientscale = diffusescale = specularscale = 0;
2274                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2275                         permutation |= SHADERPERMUTATION_GLOW;
2276                 if (r_refdef.fogenabled)
2277                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2278                 if (rsurface.texture->colormapping)
2279                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2280                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2281                 {
2282                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2283                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2284
2285                         if (r_shadow_shadowmap2ddepthbuffer)
2286                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2287                 }
2288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2289                         permutation |= SHADERPERMUTATION_REFLECTION;
2290                 if (rsurface.texture->reflectmasktexture)
2291                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2292                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2294                 // when using alphatocoverage, we don't need alphakill
2295                 if (vid.allowalphatocoverage)
2296                 {
2297                         if (r_transparent_alphatocoverage.integer)
2298                         {
2299                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2300                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2301                         }
2302                         else
2303                                 GL_AlphaToCoverage(false);
2304                 }
2305         }
2306         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2307         {
2308                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2309                 {
2310                         switch(rsurface.texture->offsetmapping)
2311                         {
2312                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2313                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2314                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315                         case OFFSETMAPPING_OFF: break;
2316                         }
2317                 }
2318                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2319                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2321                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2322                 // directional model lighting
2323                 mode = SHADERMODE_LIGHTDIRECTION;
2324                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2325                         permutation |= SHADERPERMUTATION_GLOW;
2326                 permutation |= SHADERPERMUTATION_DIFFUSE;
2327                 if (specularscale > 0)
2328                         permutation |= SHADERPERMUTATION_SPECULAR;
2329                 if (r_refdef.fogenabled)
2330                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2331                 if (rsurface.texture->colormapping)
2332                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2333                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2334                 {
2335                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2336                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2337
2338                         if (r_shadow_shadowmap2ddepthbuffer)
2339                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2340                 }
2341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2342                         permutation |= SHADERPERMUTATION_REFLECTION;
2343                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2344                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2345                 if (rsurface.texture->reflectmasktexture)
2346                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2347                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2348                 {
2349                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2350                         if (r_shadow_bouncegriddirectional)
2351                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2352                 }
2353                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2354                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2355                 // when using alphatocoverage, we don't need alphakill
2356                 if (vid.allowalphatocoverage)
2357                 {
2358                         if (r_transparent_alphatocoverage.integer)
2359                         {
2360                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2361                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2362                         }
2363                         else
2364                                 GL_AlphaToCoverage(false);
2365                 }
2366         }
2367         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2368         {
2369                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2370                 {
2371                         switch(rsurface.texture->offsetmapping)
2372                         {
2373                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2374                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2375                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2376                         case OFFSETMAPPING_OFF: break;
2377                         }
2378                 }
2379                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2380                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2382                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2383                 // ambient model lighting
2384                 mode = SHADERMODE_LIGHTDIRECTION;
2385                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2386                         permutation |= SHADERPERMUTATION_GLOW;
2387                 if (r_refdef.fogenabled)
2388                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2389                 if (rsurface.texture->colormapping)
2390                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2391                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2392                 {
2393                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2394                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2395
2396                         if (r_shadow_shadowmap2ddepthbuffer)
2397                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2398                 }
2399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2400                         permutation |= SHADERPERMUTATION_REFLECTION;
2401                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2402                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2403                 if (rsurface.texture->reflectmasktexture)
2404                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2405                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2406                 {
2407                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2408                         if (r_shadow_bouncegriddirectional)
2409                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2410                 }
2411                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413                 // when using alphatocoverage, we don't need alphakill
2414                 if (vid.allowalphatocoverage)
2415                 {
2416                         if (r_transparent_alphatocoverage.integer)
2417                         {
2418                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2419                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2420                         }
2421                         else
2422                                 GL_AlphaToCoverage(false);
2423                 }
2424         }
2425         else
2426         {
2427                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2428                 {
2429                         switch(rsurface.texture->offsetmapping)
2430                         {
2431                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2432                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2433                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2434                         case OFFSETMAPPING_OFF: break;
2435                         }
2436                 }
2437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2438                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2440                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2441                 // lightmapped wall
2442                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2443                         permutation |= SHADERPERMUTATION_GLOW;
2444                 if (r_refdef.fogenabled)
2445                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2446                 if (rsurface.texture->colormapping)
2447                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2448                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2449                 {
2450                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2451                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2452
2453                         if (r_shadow_shadowmap2ddepthbuffer)
2454                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2455                 }
2456                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2457                         permutation |= SHADERPERMUTATION_REFLECTION;
2458                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2459                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2460                 if (rsurface.texture->reflectmasktexture)
2461                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2462                 if (FAKELIGHT_ENABLED)
2463                 {
2464                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2465                         mode = SHADERMODE_FAKELIGHT;
2466                         permutation |= SHADERPERMUTATION_DIFFUSE;
2467                         if (specularscale > 0)
2468                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2469                 }
2470                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2471                 {
2472                         // deluxemapping (light direction texture)
2473                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2474                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2475                         else
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2477                         permutation |= SHADERPERMUTATION_DIFFUSE;
2478                         if (specularscale > 0)
2479                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2480                 }
2481                 else if (r_glsl_deluxemapping.integer >= 2)
2482                 {
2483                         // fake deluxemapping (uniform light direction in tangentspace)
2484                         if (rsurface.uselightmaptexture)
2485                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2486                         else
2487                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2488                         permutation |= SHADERPERMUTATION_DIFFUSE;
2489                         if (specularscale > 0)
2490                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2491                 }
2492                 else if (rsurface.uselightmaptexture)
2493                 {
2494                         // ordinary lightmapping (q1bsp, q3bsp)
2495                         mode = SHADERMODE_LIGHTMAP;
2496                 }
2497                 else
2498                 {
2499                         // ordinary vertex coloring (q3bsp)
2500                         mode = SHADERMODE_VERTEXCOLOR;
2501                 }
2502                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2503                 {
2504                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2505                         if (r_shadow_bouncegriddirectional)
2506                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2507                 }
2508                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2509                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2510                 // when using alphatocoverage, we don't need alphakill
2511                 if (vid.allowalphatocoverage)
2512                 {
2513                         if (r_transparent_alphatocoverage.integer)
2514                         {
2515                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2516                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2517                         }
2518                         else
2519                                 GL_AlphaToCoverage(false);
2520                 }
2521         }
2522         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2523                 colormod = dummy_colormod;
2524         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2525                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2526         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2527                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2528         switch(vid.renderpath)
2529         {
2530         case RENDERPATH_D3D9:
2531 #ifdef SUPPORTD3D
2532                 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);
2533                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2534                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2535                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2536                 if (mode == SHADERMODE_LIGHTSOURCE)
2537                 {
2538                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2539                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2540                 }
2541                 else
2542                 {
2543                         if (mode == SHADERMODE_LIGHTDIRECTION)
2544                         {
2545                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2546                         }
2547                 }
2548                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2549                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2550                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2551                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2552                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2553
2554                 if (mode == SHADERMODE_LIGHTSOURCE)
2555                 {
2556                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2557                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2558                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2559                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2561
2562                         // additive passes are only darkened by fog, not tinted
2563                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2564                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2565                 }
2566                 else
2567                 {
2568                         if (mode == SHADERMODE_FLATCOLOR)
2569                         {
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2571                         }
2572                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2573                         {
2574                                 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]);
2575                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2576                                 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);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2581                         }
2582                         else
2583                         {
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2586                                 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);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2589                         }
2590                         // additive passes are only darkened by fog, not tinted
2591                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2593                         else
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2595                         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);
2596                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2597                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2598                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2600                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2601                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2602                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2603                         if (mode == SHADERMODE_WATER)
2604                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2605                 }
2606                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2607                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2608                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2609                 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));
2610                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2611                 if (rsurface.texture->pantstexture)
2612                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2613                 else
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2615                 if (rsurface.texture->shirttexture)
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2617                 else
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2619                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2620                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2621                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2623                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2624                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2625                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2626                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2627                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2628                         );
2629                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2630                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2631                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2632                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2633
2634                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2635                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2636                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2637                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2638                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2639                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2642                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2643                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2644                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2645                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2646                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2647                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2648                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2649                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2650                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2651                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2652                 {
2653                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2654                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2655                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2656                 }
2657                 else
2658                 {
2659                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2660                 }
2661 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2662                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2663                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2664                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2665                 {
2666                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2667                         if (rsurface.rtlight)
2668                         {
2669                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2670                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2671                         }
2672                 }
2673 #endif
2674                 break;
2675         case RENDERPATH_D3D10:
2676                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2677                 break;
2678         case RENDERPATH_D3D11:
2679                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2680                 break;
2681         case RENDERPATH_GL20:
2682         case RENDERPATH_GLES2:
2683                 if (!vid.useinterleavedarrays)
2684                 {
2685                         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);
2686                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2687                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2688                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2689                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2690                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2693                 }
2694                 else
2695                 {
2696                         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);
2697                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2698                 }
2699                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2700                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2701                 if (mode == SHADERMODE_LIGHTSOURCE)
2702                 {
2703                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2704                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2705                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2706                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2707                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2708                         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);
2709         
2710                         // additive passes are only darkened by fog, not tinted
2711                         if (r_glsl_permutation->loc_FogColor >= 0)
2712                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2713                         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);
2714                 }
2715                 else
2716                 {
2717                         if (mode == SHADERMODE_FLATCOLOR)
2718                         {
2719                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2720                         }
2721                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2722                         {
2723                                 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]);
2724                                 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]);
2725                                 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);
2726                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2727                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2728                                 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]);
2729                                 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]);
2730                         }
2731                         else
2732                         {
2733                                 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]);
2734                                 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]);
2735                                 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);
2736                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2737                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2738                         }
2739                         // additive passes are only darkened by fog, not tinted
2740                         if (r_glsl_permutation->loc_FogColor >= 0)
2741                         {
2742                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2743                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2744                                 else
2745                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2746                         }
2747                         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);
2748                         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]);
2749                         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]);
2750                         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]);
2751                         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]);
2752                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2753                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2754                         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);
2755                         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]);
2756                 }
2757                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2758                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2759                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2760                 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]);
2761                 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]);
2762
2763                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2764                 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));
2765                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2766                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2767                 {
2768                         if (rsurface.texture->pantstexture)
2769                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2770                         else
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2772                 }
2773                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2774                 {
2775                         if (rsurface.texture->shirttexture)
2776                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2777                         else
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2779                 }
2780                 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]);
2781                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2782                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2783                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2784                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2785                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2786                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2787                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2788                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2789                         );
2790                 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);
2791                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2792                 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]);
2793                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2794                 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);}
2795                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2796
2797                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2798                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2799                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2800                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2801                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2802                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2803                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2808                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2809                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2810                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2811                 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);
2812                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2813                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2814                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2815                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2816                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2817                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2818                 {
2819                         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);
2820                         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);
2821                         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);
2822                 }
2823                 else
2824                 {
2825                         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);
2826                 }
2827                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2828                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2829                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2830                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2831                 {
2832                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2833                         if (rsurface.rtlight)
2834                         {
2835                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2836                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2837                         }
2838                 }
2839                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2840                 CHECKGLERROR
2841                 break;
2842         case RENDERPATH_GL11:
2843         case RENDERPATH_GL13:
2844         case RENDERPATH_GLES1:
2845                 break;
2846         case RENDERPATH_SOFT:
2847                 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);
2848                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2849                 R_SetupShader_SetPermutationSoft(mode, permutation);
2850                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2851                 if (mode == SHADERMODE_LIGHTSOURCE)
2852                 {
2853                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2859         
2860                         // additive passes are only darkened by fog, not tinted
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2862                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2863                 }
2864                 else
2865                 {
2866                         if (mode == SHADERMODE_FLATCOLOR)
2867                         {
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2869                         }
2870                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2871                         {
2872                                 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]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2874                                 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);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2877                                 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]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2879                         }
2880                         else
2881                         {
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2884                                 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);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2887                         }
2888                         // additive passes are only darkened by fog, not tinted
2889                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2891                         else
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2893                         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);
2894                         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]);
2895                         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]);
2896                         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]);
2897                         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]);
2898                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2899                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2901                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2902                 }
2903                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2904                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2905                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2906                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2907                 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]);
2908
2909                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2910                 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));
2911                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2912                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2913                 {
2914                         if (rsurface.texture->pantstexture)
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2916                         else
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2918                 }
2919                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2920                 {
2921                         if (rsurface.texture->shirttexture)
2922                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2923                         else
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2925                 }
2926                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2927                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2928                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2930                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2931                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2932                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2933                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2934                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2935                         );
2936                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2937                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2938                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2940
2941                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2942                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2943                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2944                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2945                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2946                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2947                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2949                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2950                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2951                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2952                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2953                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2954                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2955                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2956                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2957                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2958                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2959                 {
2960                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2961                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2962                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2963                 }
2964                 else
2965                 {
2966                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2967                 }
2968 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2969                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2970                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2971                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2972                 {
2973                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2974                         if (rsurface.rtlight)
2975                         {
2976                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2977                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2978                         }
2979                 }
2980                 break;
2981         }
2982 }
2983
2984 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2985 {
2986         // select a permutation of the lighting shader appropriate to this
2987         // combination of texture, entity, light source, and fogging, only use the
2988         // minimum features necessary to avoid wasting rendering time in the
2989         // fragment shader on features that are not being used
2990         unsigned int permutation = 0;
2991         unsigned int mode = 0;
2992         const float *lightcolorbase = rtlight->currentcolor;
2993         float ambientscale = rtlight->ambientscale;
2994         float diffusescale = rtlight->diffusescale;
2995         float specularscale = rtlight->specularscale;
2996         // this is the location of the light in view space
2997         vec3_t viewlightorigin;
2998         // this transforms from view space (camera) to light space (cubemap)
2999         matrix4x4_t viewtolight;
3000         matrix4x4_t lighttoview;
3001         float viewtolight16f[16];
3002         // light source
3003         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3004         if (rtlight->currentcubemap != r_texture_whitecube)
3005                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3006         if (diffusescale > 0)
3007                 permutation |= SHADERPERMUTATION_DIFFUSE;
3008         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3009                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3010         if (r_shadow_usingshadowmap2d)
3011         {
3012                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3013                 if (r_shadow_shadowmapvsdct)
3014                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3015
3016                 if (r_shadow_shadowmap2ddepthbuffer)
3017                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3018         }
3019         if (vid.allowalphatocoverage)
3020                 GL_AlphaToCoverage(false);
3021         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3022         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3023         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3024         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3025         switch(vid.renderpath)
3026         {
3027         case RENDERPATH_D3D9:
3028 #ifdef SUPPORTD3D
3029                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3030                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3031                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3032                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3033                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3035                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3036                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3037                 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);
3038                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3039                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3040
3041                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3042                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3043                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3044                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3045                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3046 #endif
3047                 break;
3048         case RENDERPATH_D3D10:
3049                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3050                 break;
3051         case RENDERPATH_D3D11:
3052                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053                 break;
3054         case RENDERPATH_GL20:
3055         case RENDERPATH_GLES2:
3056                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3057                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3058                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3059                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3060                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3061                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3062                 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]);
3063                 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]);
3064                 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);
3065                 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]);
3066                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3067
3068                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3069                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3070                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3071                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3072                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3073                 break;
3074         case RENDERPATH_GL11:
3075         case RENDERPATH_GL13:
3076         case RENDERPATH_GLES1:
3077                 break;
3078         case RENDERPATH_SOFT:
3079                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3080                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3081                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3082                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3085                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3086                 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]);
3087                 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);
3088                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3089                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3090
3091                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3092                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3093                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3094                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3095                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3096                 break;
3097         }
3098 }
3099
3100 #define SKINFRAME_HASH 1024
3101
3102 typedef struct
3103 {
3104         int loadsequence; // incremented each level change
3105         memexpandablearray_t array;
3106         skinframe_t *hash[SKINFRAME_HASH];
3107 }
3108 r_skinframe_t;
3109 r_skinframe_t r_skinframe;
3110
3111 void R_SkinFrame_PrepareForPurge(void)
3112 {
3113         r_skinframe.loadsequence++;
3114         // wrap it without hitting zero
3115         if (r_skinframe.loadsequence >= 200)
3116                 r_skinframe.loadsequence = 1;
3117 }
3118
3119 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3120 {
3121         if (!skinframe)
3122                 return;
3123         // mark the skinframe as used for the purging code
3124         skinframe->loadsequence = r_skinframe.loadsequence;
3125 }
3126
3127 void R_SkinFrame_Purge(void)
3128 {
3129         int i;
3130         skinframe_t *s;
3131         for (i = 0;i < SKINFRAME_HASH;i++)
3132         {
3133                 for (s = r_skinframe.hash[i];s;s = s->next)
3134                 {
3135                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3136                         {
3137                                 if (s->merged == s->base)
3138                                         s->merged = NULL;
3139                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3140                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3141                                 R_PurgeTexture(s->merged);s->merged = NULL;
3142                                 R_PurgeTexture(s->base  );s->base   = NULL;
3143                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3144                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3145                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3146                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3147                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3148                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3149                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3150                                 s->loadsequence = 0;
3151                         }
3152                 }
3153         }
3154 }
3155
3156 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3157         skinframe_t *item;
3158         char basename[MAX_QPATH];
3159
3160         Image_StripImageExtension(name, basename, sizeof(basename));
3161
3162         if( last == NULL ) {
3163                 int hashindex;
3164                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3165                 item = r_skinframe.hash[hashindex];
3166         } else {
3167                 item = last->next;
3168         }
3169
3170         // linearly search through the hash bucket
3171         for( ; item ; item = item->next ) {
3172                 if( !strcmp( item->basename, basename ) ) {
3173                         return item;
3174                 }
3175         }
3176         return NULL;
3177 }
3178
3179 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3180 {
3181         skinframe_t *item;
3182         int hashindex;
3183         char basename[MAX_QPATH];
3184
3185         Image_StripImageExtension(name, basename, sizeof(basename));
3186
3187         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3188         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3189                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3190                         break;
3191
3192         if (!item) {
3193                 rtexture_t *dyntexture;
3194                 // check whether its a dynamic texture
3195                 dyntexture = CL_GetDynTexture( basename );
3196                 if (!add && !dyntexture)
3197                         return NULL;
3198                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3199                 memset(item, 0, sizeof(*item));
3200                 strlcpy(item->basename, basename, sizeof(item->basename));
3201                 item->base = dyntexture; // either NULL or dyntexture handle
3202                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3203                 item->comparewidth = comparewidth;
3204                 item->compareheight = compareheight;
3205                 item->comparecrc = comparecrc;
3206                 item->next = r_skinframe.hash[hashindex];
3207                 r_skinframe.hash[hashindex] = item;
3208         }
3209         else if (textureflags & TEXF_FORCE_RELOAD)
3210         {
3211                 rtexture_t *dyntexture;
3212                 // check whether its a dynamic texture
3213                 dyntexture = CL_GetDynTexture( basename );
3214                 if (!add && !dyntexture)
3215                         return NULL;
3216                 if (item->merged == item->base)
3217                         item->merged = NULL;
3218                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3219                 R_PurgeTexture(item->stain );item->stain  = NULL;
3220                 R_PurgeTexture(item->merged);item->merged = NULL;
3221                 R_PurgeTexture(item->base  );item->base   = NULL;
3222                 R_PurgeTexture(item->pants );item->pants  = NULL;
3223                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3224                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3225                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3226                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3227                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3228         R_PurgeTexture(item->reflect);item->reflect = NULL;
3229                 item->loadsequence = 0;
3230         }
3231         else if( item->base == NULL )
3232         {
3233                 rtexture_t *dyntexture;
3234                 // check whether its a dynamic texture
3235                 // 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]
3236                 dyntexture = CL_GetDynTexture( basename );
3237                 item->base = dyntexture; // either NULL or dyntexture handle
3238         }
3239
3240         R_SkinFrame_MarkUsed(item);
3241         return item;
3242 }
3243
3244 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3245         { \
3246                 unsigned long long avgcolor[5], wsum; \
3247                 int pix, comp, w; \
3248                 avgcolor[0] = 0; \
3249                 avgcolor[1] = 0; \
3250                 avgcolor[2] = 0; \
3251                 avgcolor[3] = 0; \
3252                 avgcolor[4] = 0; \
3253                 wsum = 0; \
3254                 for(pix = 0; pix < cnt; ++pix) \
3255                 { \
3256                         w = 0; \
3257                         for(comp = 0; comp < 3; ++comp) \
3258                                 w += getpixel; \
3259                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3260                         { \
3261                                 ++wsum; \
3262                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3263                                 w = getpixel; \
3264                                 for(comp = 0; comp < 3; ++comp) \
3265                                         avgcolor[comp] += getpixel * w; \
3266                                 avgcolor[3] += w; \
3267                         } \
3268                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3269                         avgcolor[4] += getpixel; \
3270                 } \
3271                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3272                         avgcolor[3] = 1; \
3273                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3274                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3275                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3276                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3277         }
3278
3279 extern cvar_t gl_picmip;
3280 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3281 {
3282         int j;
3283         unsigned char *pixels;
3284         unsigned char *bumppixels;
3285         unsigned char *basepixels = NULL;
3286         int basepixels_width = 0;
3287         int basepixels_height = 0;
3288         skinframe_t *skinframe;
3289         rtexture_t *ddsbase = NULL;
3290         qboolean ddshasalpha = false;
3291         float ddsavgcolor[4];
3292         char basename[MAX_QPATH];
3293         int miplevel = R_PicmipForFlags(textureflags);
3294         int savemiplevel = miplevel;
3295         int mymiplevel;
3296         char vabuf[1024];
3297
3298         if (cls.state == ca_dedicated)
3299                 return NULL;
3300
3301         // return an existing skinframe if already loaded
3302         // if loading of the first image fails, don't make a new skinframe as it
3303         // would cause all future lookups of this to be missing
3304         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3305         if (skinframe && skinframe->base)
3306                 return skinframe;
3307
3308         Image_StripImageExtension(name, basename, sizeof(basename));
3309
3310         // check for DDS texture file first
3311         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3312         {
3313                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3314                 if (basepixels == NULL)
3315                         return NULL;
3316         }
3317
3318         // FIXME handle miplevel
3319
3320         if (developer_loading.integer)
3321                 Con_Printf("loading skin \"%s\"\n", name);
3322
3323         // we've got some pixels to store, so really allocate this new texture now
3324         if (!skinframe)
3325                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3326         textureflags &= ~TEXF_FORCE_RELOAD;
3327         skinframe->stain = NULL;
3328         skinframe->merged = NULL;
3329         skinframe->base = NULL;
3330         skinframe->pants = NULL;
3331         skinframe->shirt = NULL;
3332         skinframe->nmap = NULL;
3333         skinframe->gloss = NULL;
3334         skinframe->glow = NULL;
3335         skinframe->fog = NULL;
3336         skinframe->reflect = NULL;
3337         skinframe->hasalpha = false;
3338
3339         if (ddsbase)
3340         {
3341                 skinframe->base = ddsbase;
3342                 skinframe->hasalpha = ddshasalpha;
3343                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3344                 if (r_loadfog && skinframe->hasalpha)
3345                         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);
3346                 //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]);
3347         }
3348         else
3349         {
3350                 basepixels_width = image_width;
3351                 basepixels_height = image_height;
3352                 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);
3353                 if (textureflags & TEXF_ALPHA)
3354                 {
3355                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3356                         {
3357                                 if (basepixels[j] < 255)
3358                                 {
3359                                         skinframe->hasalpha = true;
3360                                         break;
3361                                 }
3362                         }
3363                         if (r_loadfog && skinframe->hasalpha)
3364                         {
3365                                 // has transparent pixels
3366                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3367                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3368                                 {
3369                                         pixels[j+0] = 255;
3370                                         pixels[j+1] = 255;
3371                                         pixels[j+2] = 255;
3372                                         pixels[j+3] = basepixels[j+3];
3373                                 }
3374                                 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);
3375                                 Mem_Free(pixels);
3376                         }
3377                 }
3378                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3379 #ifndef USE_GLES2
3380                 //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]);
3381                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3382                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3383                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3384                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3385 #endif
3386         }
3387
3388         if (r_loaddds)
3389         {
3390                 mymiplevel = savemiplevel;
3391                 if (r_loadnormalmap)
3392                         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);
3393                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3394                 if (r_loadgloss)
3395                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3396                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3397                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3398                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3399         }
3400
3401         // _norm is the name used by tenebrae and has been adopted as standard
3402         if (r_loadnormalmap && skinframe->nmap == NULL)
3403         {
3404                 mymiplevel = savemiplevel;
3405                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3406                 {
3407                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3408                         Mem_Free(pixels);
3409                         pixels = NULL;
3410                 }
3411                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3412                 {
3413                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3414                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3415                         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);
3416                         Mem_Free(pixels);
3417                         Mem_Free(bumppixels);
3418                 }
3419                 else if (r_shadow_bumpscale_basetexture.value > 0)
3420                 {
3421                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3422                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3423                         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);
3424                         Mem_Free(pixels);
3425                 }
3426 #ifndef USE_GLES2
3427                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3428                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3429 #endif
3430         }
3431
3432         // _luma is supported only for tenebrae compatibility
3433         // _glow is the preferred name
3434         mymiplevel = savemiplevel;
3435         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))))
3436         {
3437                 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);
3438 #ifndef USE_GLES2
3439                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3440                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3441 #endif
3442                 Mem_Free(pixels);pixels = NULL;
3443         }
3444
3445         mymiplevel = savemiplevel;
3446         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3447         {
3448                 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);
3449 #ifndef USE_GLES2
3450                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3451                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3452 #endif
3453                 Mem_Free(pixels);
3454                 pixels = NULL;
3455         }
3456
3457         mymiplevel = savemiplevel;
3458         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3459         {
3460                 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);
3461 #ifndef USE_GLES2
3462                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3463                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3464 #endif
3465                 Mem_Free(pixels);
3466                 pixels = NULL;
3467         }
3468
3469         mymiplevel = savemiplevel;
3470         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3471         {
3472                 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);
3473 #ifndef USE_GLES2
3474                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3475                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3476 #endif
3477                 Mem_Free(pixels);
3478                 pixels = NULL;
3479         }
3480
3481         mymiplevel = savemiplevel;
3482         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3483         {
3484                 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);
3485 #ifndef USE_GLES2
3486                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3487                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3488 #endif
3489                 Mem_Free(pixels);
3490                 pixels = NULL;
3491         }
3492
3493         if (basepixels)
3494                 Mem_Free(basepixels);
3495
3496         return skinframe;
3497 }
3498
3499 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3500 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3501 {
3502         int i;
3503         unsigned char *temp1, *temp2;
3504         skinframe_t *skinframe;
3505         char vabuf[1024];
3506
3507         if (cls.state == ca_dedicated)
3508                 return NULL;
3509
3510         // if already loaded just return it, otherwise make a new skinframe
3511         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3512         if (skinframe->base)
3513                 return skinframe;
3514         textureflags &= ~TEXF_FORCE_RELOAD;
3515
3516         skinframe->stain = NULL;
3517         skinframe->merged = NULL;
3518         skinframe->base = NULL;
3519         skinframe->pants = NULL;
3520         skinframe->shirt = NULL;
3521         skinframe->nmap = NULL;
3522         skinframe->gloss = NULL;
3523         skinframe->glow = NULL;
3524         skinframe->fog = NULL;
3525         skinframe->reflect = NULL;
3526         skinframe->hasalpha = false;
3527
3528         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3529         if (!skindata)
3530                 return NULL;
3531
3532         if (developer_loading.integer)
3533                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3534
3535         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3536         {
3537                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3538                 temp2 = temp1 + width * height * 4;
3539                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3540                 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);
3541                 Mem_Free(temp1);
3542         }
3543         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3544         if (textureflags & TEXF_ALPHA)
3545         {
3546                 for (i = 3;i < width * height * 4;i += 4)
3547                 {
3548                         if (skindata[i] < 255)
3549                         {
3550                                 skinframe->hasalpha = true;
3551                                 break;
3552                         }
3553                 }
3554                 if (r_loadfog && skinframe->hasalpha)
3555                 {
3556                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3557                         memcpy(fogpixels, skindata, width * height * 4);
3558                         for (i = 0;i < width * height * 4;i += 4)
3559                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3560                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3561                         Mem_Free(fogpixels);
3562                 }
3563         }
3564
3565         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3566         //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]);
3567
3568         return skinframe;
3569 }
3570
3571 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3572 {
3573         int i;
3574         int featuresmask;
3575         skinframe_t *skinframe;
3576
3577         if (cls.state == ca_dedicated)
3578                 return NULL;
3579
3580         // if already loaded just return it, otherwise make a new skinframe
3581         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3582         if (skinframe->base)
3583                 return skinframe;
3584         //textureflags &= ~TEXF_FORCE_RELOAD;
3585
3586         skinframe->stain = NULL;
3587         skinframe->merged = NULL;
3588         skinframe->base = NULL;
3589         skinframe->pants = NULL;
3590         skinframe->shirt = NULL;
3591         skinframe->nmap = NULL;
3592         skinframe->gloss = NULL;
3593         skinframe->glow = NULL;
3594         skinframe->fog = NULL;
3595         skinframe->reflect = NULL;
3596         skinframe->hasalpha = false;
3597
3598         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3599         if (!skindata)
3600                 return NULL;
3601
3602         if (developer_loading.integer)
3603                 Con_Printf("loading quake skin \"%s\"\n", name);
3604
3605         // 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)
3606         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3607         memcpy(skinframe->qpixels, skindata, width*height);
3608         skinframe->qwidth = width;
3609         skinframe->qheight = height;
3610
3611         featuresmask = 0;
3612         for (i = 0;i < width * height;i++)
3613                 featuresmask |= palette_featureflags[skindata[i]];
3614
3615         skinframe->hasalpha = false;
3616         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3617         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3618         skinframe->qgeneratemerged = true;
3619         skinframe->qgeneratebase = skinframe->qhascolormapping;
3620         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3621
3622         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3623         //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]);
3624
3625         return skinframe;
3626 }
3627
3628 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3629 {
3630         int width;
3631         int height;
3632         unsigned char *skindata;
3633         char vabuf[1024];
3634
3635         if (!skinframe->qpixels)
3636                 return;
3637
3638         if (!skinframe->qhascolormapping)
3639                 colormapped = false;
3640
3641         if (colormapped)
3642         {
3643                 if (!skinframe->qgeneratebase)
3644                         return;
3645         }
3646         else
3647         {
3648                 if (!skinframe->qgeneratemerged)
3649                         return;
3650         }
3651
3652         width = skinframe->qwidth;
3653         height = skinframe->qheight;
3654         skindata = skinframe->qpixels;
3655
3656         if (skinframe->qgeneratenmap)
3657         {
3658                 unsigned char *temp1, *temp2;
3659                 skinframe->qgeneratenmap = false;
3660                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3661                 temp2 = temp1 + width * height * 4;
3662                 // use either a custom palette or the quake palette
3663                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3664                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3665                 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);
3666                 Mem_Free(temp1);
3667         }
3668
3669         if (skinframe->qgenerateglow)
3670         {
3671                 skinframe->qgenerateglow = false;
3672                 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
3673         }
3674
3675         if (colormapped)
3676         {
3677                 skinframe->qgeneratebase = false;
3678                 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);
3679                 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);
3680                 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);
3681         }
3682         else
3683         {
3684                 skinframe->qgeneratemerged = false;
3685                 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);
3686         }
3687
3688         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3689         {
3690                 Mem_Free(skinframe->qpixels);
3691                 skinframe->qpixels = NULL;
3692         }
3693 }
3694
3695 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)
3696 {
3697         int i;
3698         skinframe_t *skinframe;
3699         char vabuf[1024];
3700
3701         if (cls.state == ca_dedicated)
3702                 return NULL;
3703
3704         // if already loaded just return it, otherwise make a new skinframe
3705         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3706         if (skinframe->base)
3707                 return skinframe;
3708         textureflags &= ~TEXF_FORCE_RELOAD;
3709
3710         skinframe->stain = NULL;
3711         skinframe->merged = NULL;
3712         skinframe->base = NULL;
3713         skinframe->pants = NULL;
3714         skinframe->shirt = NULL;
3715         skinframe->nmap = NULL;
3716         skinframe->gloss = NULL;
3717         skinframe->glow = NULL;
3718         skinframe->fog = NULL;
3719         skinframe->reflect = NULL;
3720         skinframe->hasalpha = false;
3721
3722         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3723         if (!skindata)
3724                 return NULL;
3725
3726         if (developer_loading.integer)
3727                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3728
3729         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3730         if (textureflags & TEXF_ALPHA)
3731         {
3732                 for (i = 0;i < width * height;i++)
3733                 {
3734                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3735                         {
3736                                 skinframe->hasalpha = true;
3737                                 break;
3738                         }
3739                 }
3740                 if (r_loadfog && skinframe->hasalpha)
3741                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3742         }
3743
3744         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3745         //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]);
3746
3747         return skinframe;
3748 }
3749
3750 skinframe_t *R_SkinFrame_LoadMissing(void)
3751 {
3752         skinframe_t *skinframe;
3753
3754         if (cls.state == ca_dedicated)
3755                 return NULL;
3756
3757         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3758         skinframe->stain = NULL;
3759         skinframe->merged = NULL;
3760         skinframe->base = NULL;
3761         skinframe->pants = NULL;
3762         skinframe->shirt = NULL;
3763         skinframe->nmap = NULL;
3764         skinframe->gloss = NULL;
3765         skinframe->glow = NULL;
3766         skinframe->fog = NULL;
3767         skinframe->reflect = NULL;
3768         skinframe->hasalpha = false;
3769
3770         skinframe->avgcolor[0] = rand() / RAND_MAX;
3771         skinframe->avgcolor[1] = rand() / RAND_MAX;
3772         skinframe->avgcolor[2] = rand() / RAND_MAX;
3773         skinframe->avgcolor[3] = 1;
3774
3775         return skinframe;
3776 }
3777
3778 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3779 typedef struct suffixinfo_s
3780 {
3781         const char *suffix;
3782         qboolean flipx, flipy, flipdiagonal;
3783 }
3784 suffixinfo_t;
3785 static suffixinfo_t suffix[3][6] =
3786 {
3787         {
3788                 {"px",   false, false, false},
3789                 {"nx",   false, false, false},
3790                 {"py",   false, false, false},
3791                 {"ny",   false, false, false},
3792                 {"pz",   false, false, false},
3793                 {"nz",   false, false, false}
3794         },
3795         {
3796                 {"posx", false, false, false},
3797                 {"negx", false, false, false},
3798                 {"posy", false, false, false},
3799                 {"negy", false, false, false},
3800                 {"posz", false, false, false},
3801                 {"negz", false, false, false}
3802         },
3803         {
3804                 {"rt",    true, false,  true},
3805                 {"lf",   false,  true,  true},
3806                 {"ft",    true,  true, false},
3807                 {"bk",   false, false, false},
3808                 {"up",    true, false,  true},
3809                 {"dn",    true, false,  true}
3810         }
3811 };
3812
3813 static int componentorder[4] = {0, 1, 2, 3};
3814
3815 static rtexture_t *R_LoadCubemap(const char *basename)
3816 {
3817         int i, j, cubemapsize;
3818         unsigned char *cubemappixels, *image_buffer;
3819         rtexture_t *cubemaptexture;
3820         char name[256];
3821         // must start 0 so the first loadimagepixels has no requested width/height
3822         cubemapsize = 0;
3823         cubemappixels = NULL;
3824         cubemaptexture = NULL;
3825         // keep trying different suffix groups (posx, px, rt) until one loads
3826         for (j = 0;j < 3 && !cubemappixels;j++)
3827         {
3828                 // load the 6 images in the suffix group
3829                 for (i = 0;i < 6;i++)
3830                 {
3831                         // generate an image name based on the base and and suffix
3832                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3833                         // load it
3834                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3835                         {
3836                                 // an image loaded, make sure width and height are equal
3837                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3838                                 {
3839                                         // if this is the first image to load successfully, allocate the cubemap memory
3840                                         if (!cubemappixels && image_width >= 1)
3841                                         {
3842                                                 cubemapsize = image_width;
3843                                                 // note this clears to black, so unavailable sides are black
3844                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3845                                         }
3846                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3847                                         if (cubemappixels)
3848                                                 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);
3849                                 }
3850                                 else
3851                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3852                                 // free the image
3853                                 Mem_Free(image_buffer);
3854                         }
3855                 }
3856         }
3857         // if a cubemap loaded, upload it
3858         if (cubemappixels)
3859         {
3860                 if (developer_loading.integer)
3861                         Con_Printf("loading cubemap \"%s\"\n", basename);
3862
3863                 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);
3864                 Mem_Free(cubemappixels);
3865         }
3866         else
3867         {
3868                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3869                 if (developer_loading.integer)
3870                 {
3871                         Con_Printf("(tried tried images ");
3872                         for (j = 0;j < 3;j++)
3873                                 for (i = 0;i < 6;i++)
3874                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3875                         Con_Print(" and was unable to find any of them).\n");
3876                 }
3877         }
3878         return cubemaptexture;
3879 }
3880
3881 rtexture_t *R_GetCubemap(const char *basename)
3882 {
3883         int i;
3884         for (i = 0;i < r_texture_numcubemaps;i++)
3885                 if (r_texture_cubemaps[i] != NULL)
3886                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3887                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3888         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3889                 return r_texture_whitecube;
3890         r_texture_numcubemaps++;
3891         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3892         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3893         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3894         return r_texture_cubemaps[i]->texture;
3895 }
3896
3897 static void R_Main_FreeViewCache(void)
3898 {
3899         if (r_refdef.viewcache.entityvisible)
3900                 Mem_Free(r_refdef.viewcache.entityvisible);
3901         if (r_refdef.viewcache.world_pvsbits)
3902                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3903         if (r_refdef.viewcache.world_leafvisible)
3904                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3905         if (r_refdef.viewcache.world_surfacevisible)
3906                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3907         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3908 }
3909
3910 static void R_Main_ResizeViewCache(void)
3911 {
3912         int numentities = r_refdef.scene.numentities;
3913         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3914         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3915         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3916         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3917         if (r_refdef.viewcache.maxentities < numentities)
3918         {
3919                 r_refdef.viewcache.maxentities = numentities;
3920                 if (r_refdef.viewcache.entityvisible)
3921                         Mem_Free(r_refdef.viewcache.entityvisible);
3922                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3923         }
3924         if (r_refdef.viewcache.world_numclusters != numclusters)
3925         {
3926                 r_refdef.viewcache.world_numclusters = numclusters;
3927                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3928                 if (r_refdef.viewcache.world_pvsbits)
3929                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3930                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3931         }
3932         if (r_refdef.viewcache.world_numleafs != numleafs)
3933         {
3934                 r_refdef.viewcache.world_numleafs = numleafs;
3935                 if (r_refdef.viewcache.world_leafvisible)
3936                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3937                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3938         }
3939         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3940         {
3941                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3942                 if (r_refdef.viewcache.world_surfacevisible)
3943                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3944                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3945         }
3946 }
3947
3948 extern rtexture_t *loadingscreentexture;
3949 static void gl_main_start(void)
3950 {
3951         loadingscreentexture = NULL;
3952         r_texture_blanknormalmap = NULL;
3953         r_texture_white = NULL;
3954         r_texture_grey128 = NULL;
3955         r_texture_black = NULL;
3956         r_texture_whitecube = NULL;
3957         r_texture_normalizationcube = NULL;
3958         r_texture_fogattenuation = NULL;
3959         r_texture_fogheighttexture = NULL;
3960         r_texture_gammaramps = NULL;
3961         r_texture_numcubemaps = 0;
3962
3963         r_loaddds = r_texture_dds_load.integer != 0;
3964         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3965
3966         switch(vid.renderpath)
3967         {
3968         case RENDERPATH_GL20:
3969         case RENDERPATH_D3D9:
3970         case RENDERPATH_D3D10:
3971         case RENDERPATH_D3D11:
3972         case RENDERPATH_SOFT:
3973         case RENDERPATH_GLES2:
3974                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3975                 Cvar_SetValueQuick(&gl_combine, 1);
3976                 Cvar_SetValueQuick(&r_glsl, 1);
3977                 r_loadnormalmap = true;
3978                 r_loadgloss = true;
3979                 r_loadfog = false;
3980                 break;
3981         case RENDERPATH_GL13:
3982         case RENDERPATH_GLES1:
3983                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3984                 Cvar_SetValueQuick(&gl_combine, 1);
3985                 Cvar_SetValueQuick(&r_glsl, 0);
3986                 r_loadnormalmap = false;
3987                 r_loadgloss = false;
3988                 r_loadfog = true;
3989                 break;
3990         case RENDERPATH_GL11:
3991                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3992                 Cvar_SetValueQuick(&gl_combine, 0);
3993                 Cvar_SetValueQuick(&r_glsl, 0);
3994                 r_loadnormalmap = false;
3995                 r_loadgloss = false;
3996                 r_loadfog = true;
3997                 break;
3998         }
3999
4000         R_AnimCache_Free();
4001         R_FrameData_Reset();
4002
4003         r_numqueries = 0;
4004         r_maxqueries = 0;
4005         memset(r_queries, 0, sizeof(r_queries));
4006
4007         r_qwskincache = NULL;
4008         r_qwskincache_size = 0;
4009
4010         // due to caching of texture_t references, the collision cache must be reset
4011         Collision_Cache_Reset(true);
4012
4013         // set up r_skinframe loading system for textures
4014         memset(&r_skinframe, 0, sizeof(r_skinframe));
4015         r_skinframe.loadsequence = 1;
4016         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4017
4018         r_main_texturepool = R_AllocTexturePool();
4019         R_BuildBlankTextures();
4020         R_BuildNoTexture();
4021         if (vid.support.arb_texture_cube_map)
4022         {
4023                 R_BuildWhiteCube();
4024                 R_BuildNormalizationCube();
4025         }
4026         r_texture_fogattenuation = NULL;
4027         r_texture_fogheighttexture = NULL;
4028         r_texture_gammaramps = NULL;
4029         //r_texture_fogintensity = NULL;
4030         memset(&r_fb, 0, sizeof(r_fb));
4031         r_glsl_permutation = NULL;
4032         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4033         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4034         glslshaderstring = NULL;
4035 #ifdef SUPPORTD3D
4036         r_hlsl_permutation = NULL;
4037         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4038         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4039 #endif
4040         hlslshaderstring = NULL;
4041         memset(&r_svbsp, 0, sizeof (r_svbsp));
4042
4043         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4044         r_texture_numcubemaps = 0;
4045
4046         r_refdef.fogmasktable_density = 0;
4047 }
4048
4049 static void gl_main_shutdown(void)
4050 {
4051         R_AnimCache_Free();
4052         R_FrameData_Reset();
4053
4054         R_Main_FreeViewCache();
4055
4056         switch(vid.renderpath)
4057         {
4058         case RENDERPATH_GL11:
4059         case RENDERPATH_GL13:
4060         case RENDERPATH_GL20:
4061         case RENDERPATH_GLES1:
4062         case RENDERPATH_GLES2:
4063 #ifdef GL_SAMPLES_PASSED_ARB
4064                 if (r_maxqueries)
4065                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4066 #endif
4067                 break;
4068         case RENDERPATH_D3D9:
4069                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4070                 break;
4071         case RENDERPATH_D3D10:
4072                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4073                 break;
4074         case RENDERPATH_D3D11:
4075                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4076                 break;
4077         case RENDERPATH_SOFT:
4078                 break;
4079         }
4080
4081         r_numqueries = 0;
4082         r_maxqueries = 0;
4083         memset(r_queries, 0, sizeof(r_queries));
4084
4085         r_qwskincache = NULL;
4086         r_qwskincache_size = 0;
4087
4088         // clear out the r_skinframe state
4089         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4090         memset(&r_skinframe, 0, sizeof(r_skinframe));
4091
4092         if (r_svbsp.nodes)
4093                 Mem_Free(r_svbsp.nodes);
4094         memset(&r_svbsp, 0, sizeof (r_svbsp));
4095         R_FreeTexturePool(&r_main_texturepool);
4096         loadingscreentexture = NULL;
4097         r_texture_blanknormalmap = NULL;
4098         r_texture_white = NULL;
4099         r_texture_grey128 = NULL;
4100         r_texture_black = NULL;
4101         r_texture_whitecube = NULL;
4102         r_texture_normalizationcube = NULL;
4103         r_texture_fogattenuation = NULL;
4104         r_texture_fogheighttexture = NULL;
4105         r_texture_gammaramps = NULL;
4106         r_texture_numcubemaps = 0;
4107         //r_texture_fogintensity = NULL;
4108         memset(&r_fb, 0, sizeof(r_fb));
4109         R_GLSL_Restart_f();
4110
4111         r_glsl_permutation = NULL;
4112         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4113         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4114         glslshaderstring = NULL;
4115 #ifdef SUPPORTD3D
4116         r_hlsl_permutation = NULL;
4117         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4118         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4119 #endif
4120         hlslshaderstring = NULL;
4121 }
4122
4123 static void gl_main_newmap(void)
4124 {
4125         // FIXME: move this code to client
4126         char *entities, entname[MAX_QPATH];
4127         if (r_qwskincache)
4128                 Mem_Free(r_qwskincache);
4129         r_qwskincache = NULL;
4130         r_qwskincache_size = 0;
4131         if (cl.worldmodel)
4132         {
4133                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4134                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4135                 {
4136                         CL_ParseEntityLump(entities);
4137                         Mem_Free(entities);
4138                         return;
4139                 }
4140                 if (cl.worldmodel->brush.entities)
4141                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4142         }
4143         R_Main_FreeViewCache();
4144
4145         R_FrameData_Reset();
4146 }
4147
4148 void GL_Main_Init(void)
4149 {
4150         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4151
4152         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4153         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4154         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4155         if (gamemode == GAME_NEHAHRA)
4156         {
4157                 Cvar_RegisterVariable (&gl_fogenable);
4158                 Cvar_RegisterVariable (&gl_fogdensity);
4159                 Cvar_RegisterVariable (&gl_fogred);
4160                 Cvar_RegisterVariable (&gl_foggreen);
4161                 Cvar_RegisterVariable (&gl_fogblue);
4162                 Cvar_RegisterVariable (&gl_fogstart);
4163                 Cvar_RegisterVariable (&gl_fogend);
4164                 Cvar_RegisterVariable (&gl_skyclip);
4165         }
4166         Cvar_RegisterVariable(&r_motionblur);
4167         Cvar_RegisterVariable(&r_damageblur);
4168         Cvar_RegisterVariable(&r_motionblur_averaging);
4169         Cvar_RegisterVariable(&r_motionblur_randomize);
4170         Cvar_RegisterVariable(&r_motionblur_minblur);
4171         Cvar_RegisterVariable(&r_motionblur_maxblur);
4172         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4173         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4174         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4175         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4176         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4177         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4178         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4179         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4180         Cvar_RegisterVariable(&r_equalize_entities_by);
4181         Cvar_RegisterVariable(&r_equalize_entities_to);
4182         Cvar_RegisterVariable(&r_depthfirst);
4183         Cvar_RegisterVariable(&r_useinfinitefarclip);
4184         Cvar_RegisterVariable(&r_farclip_base);
4185         Cvar_RegisterVariable(&r_farclip_world);
4186         Cvar_RegisterVariable(&r_nearclip);
4187         Cvar_RegisterVariable(&r_deformvertexes);
4188         Cvar_RegisterVariable(&r_transparent);
4189         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4190         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4191         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4192         Cvar_RegisterVariable(&r_showoverdraw);
4193         Cvar_RegisterVariable(&r_showbboxes);
4194         Cvar_RegisterVariable(&r_showsurfaces);
4195         Cvar_RegisterVariable(&r_showtris);
4196         Cvar_RegisterVariable(&r_shownormals);
4197         Cvar_RegisterVariable(&r_showlighting);
4198         Cvar_RegisterVariable(&r_showshadowvolumes);
4199         Cvar_RegisterVariable(&r_showcollisionbrushes);
4200         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4201         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4202         Cvar_RegisterVariable(&r_showdisabledepthtest);
4203         Cvar_RegisterVariable(&r_drawportals);
4204         Cvar_RegisterVariable(&r_drawentities);
4205         Cvar_RegisterVariable(&r_draw2d);
4206         Cvar_RegisterVariable(&r_drawworld);
4207         Cvar_RegisterVariable(&r_cullentities_trace);
4208         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4209         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4210         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4211         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4212         Cvar_RegisterVariable(&r_sortentities);
4213         Cvar_RegisterVariable(&r_drawviewmodel);
4214         Cvar_RegisterVariable(&r_drawexteriormodel);
4215         Cvar_RegisterVariable(&r_speeds);
4216         Cvar_RegisterVariable(&r_fullbrights);
4217         Cvar_RegisterVariable(&r_wateralpha);
4218         Cvar_RegisterVariable(&r_dynamic);
4219         Cvar_RegisterVariable(&r_fakelight);
4220         Cvar_RegisterVariable(&r_fakelight_intensity);
4221         Cvar_RegisterVariable(&r_fullbright);
4222         Cvar_RegisterVariable(&r_shadows);
4223         Cvar_RegisterVariable(&r_shadows_darken);
4224         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4225         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4226         Cvar_RegisterVariable(&r_shadows_throwdistance);
4227         Cvar_RegisterVariable(&r_shadows_throwdirection);
4228         Cvar_RegisterVariable(&r_shadows_focus);
4229         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4230         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4231         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4232         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4233         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4234         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4235         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4236         Cvar_RegisterVariable(&r_fog_exp2);
4237         Cvar_RegisterVariable(&r_fog_clear);
4238         Cvar_RegisterVariable(&r_drawfog);
4239         Cvar_RegisterVariable(&r_transparentdepthmasking);
4240         Cvar_RegisterVariable(&r_transparent_sortmindist);
4241         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4242         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4243         Cvar_RegisterVariable(&r_texture_dds_load);
4244         Cvar_RegisterVariable(&r_texture_dds_save);
4245         Cvar_RegisterVariable(&r_textureunits);
4246         Cvar_RegisterVariable(&gl_combine);
4247         Cvar_RegisterVariable(&r_usedepthtextures);
4248         Cvar_RegisterVariable(&r_viewfbo);
4249         Cvar_RegisterVariable(&r_viewscale);
4250         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4251         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4256         Cvar_RegisterVariable(&r_glsl);
4257         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4258         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4259         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4266         Cvar_RegisterVariable(&r_glsl_postprocess);
4267         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4275         Cvar_RegisterVariable(&r_celshading);
4276         Cvar_RegisterVariable(&r_celoutlines);
4277
4278         Cvar_RegisterVariable(&r_water);
4279         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4280         Cvar_RegisterVariable(&r_water_clippingplanebias);
4281         Cvar_RegisterVariable(&r_water_refractdistort);
4282         Cvar_RegisterVariable(&r_water_reflectdistort);
4283         Cvar_RegisterVariable(&r_water_scissormode);
4284         Cvar_RegisterVariable(&r_water_lowquality);
4285         Cvar_RegisterVariable(&r_water_hideplayer);
4286         Cvar_RegisterVariable(&r_water_fbo);
4287
4288         Cvar_RegisterVariable(&r_lerpsprites);
4289         Cvar_RegisterVariable(&r_lerpmodels);
4290         Cvar_RegisterVariable(&r_lerplightstyles);
4291         Cvar_RegisterVariable(&r_waterscroll);
4292         Cvar_RegisterVariable(&r_bloom);
4293         Cvar_RegisterVariable(&r_bloom_colorscale);
4294         Cvar_RegisterVariable(&r_bloom_brighten);
4295         Cvar_RegisterVariable(&r_bloom_blur);
4296         Cvar_RegisterVariable(&r_bloom_resolution);
4297         Cvar_RegisterVariable(&r_bloom_colorexponent);
4298         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4299         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4300         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4301         Cvar_RegisterVariable(&r_hdr_glowintensity);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4310         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4311         Cvar_RegisterVariable(&developer_texturelogging);
4312         Cvar_RegisterVariable(&gl_lightmaps);
4313         Cvar_RegisterVariable(&r_test);
4314         Cvar_RegisterVariable(&r_glsl_saturation);
4315         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4316         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4317         Cvar_RegisterVariable(&r_framedatasize);
4318         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4319                 Cvar_SetValue("r_fullbrights", 0);
4320         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4321 }
4322
4323 void Render_Init(void)
4324 {
4325         gl_backend_init();
4326         R_Textures_Init();
4327         GL_Main_Init();
4328         Font_Init();
4329         GL_Draw_Init();
4330         R_Shadow_Init();
4331         R_Sky_Init();
4332         GL_Surf_Init();
4333         Sbar_Init();
4334         R_Particles_Init();
4335         R_Explosion_Init();
4336         R_LightningBeams_Init();
4337         Mod_RenderInit();
4338 }
4339
4340 /*
4341 ===============
4342 GL_Init
4343 ===============
4344 */
4345 #ifndef USE_GLES2
4346 extern char *ENGINE_EXTENSIONS;
4347 void GL_Init (void)
4348 {
4349         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4350         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4351         gl_version = (const char *)qglGetString(GL_VERSION);
4352         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4353
4354         if (!gl_extensions)
4355                 gl_extensions = "";
4356         if (!gl_platformextensions)
4357                 gl_platformextensions = "";
4358
4359         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4360         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4361         Con_Printf("GL_VERSION: %s\n", gl_version);
4362         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4363         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4364
4365         VID_CheckExtensions();
4366
4367         // LordHavoc: report supported extensions
4368         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4369
4370         // clear to black (loading plaque will be seen over this)
4371         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4372 }
4373 #endif
4374
4375 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4376 {
4377         int i;
4378         mplane_t *p;
4379         if (r_trippy.integer)
4380                 return false;
4381         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4382         {
4383                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4384                 if (i == 4)
4385                         continue;
4386                 p = r_refdef.view.frustum + i;
4387                 switch(p->signbits)
4388                 {
4389                 default:
4390                 case 0:
4391                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 1:
4395                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 2:
4399                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 3:
4403                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 4:
4407                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 5:
4411                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 6:
4415                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 7:
4419                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 }
4423         }
4424         return false;
4425 }
4426
4427 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4428 {
4429         int i;
4430         const mplane_t *p;
4431         if (r_trippy.integer)
4432                 return false;
4433         for (i = 0;i < numplanes;i++)
4434         {
4435                 p = planes + i;
4436                 switch(p->signbits)
4437                 {
4438                 default:
4439                 case 0:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 1:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 2:
4448                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 3:
4452                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 4:
4456                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 5:
4460                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 6:
4464                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 7:
4468                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 }
4472         }
4473         return false;
4474 }
4475
4476 //==================================================================================
4477
4478 // LordHavoc: this stores temporary data used within the same frame
4479
4480 typedef struct r_framedata_mem_s
4481 {
4482         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4483         size_t size; // how much usable space
4484         size_t current; // how much space in use
4485         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4486         size_t wantedsize; // how much space was allocated
4487         unsigned char *data; // start of real data (16byte aligned)
4488 }
4489 r_framedata_mem_t;
4490
4491 static r_framedata_mem_t *r_framedata_mem;
4492
4493 void R_FrameData_Reset(void)
4494 {
4495         while (r_framedata_mem)
4496         {
4497                 r_framedata_mem_t *next = r_framedata_mem->purge;
4498                 Mem_Free(r_framedata_mem);
4499                 r_framedata_mem = next;
4500         }
4501 }
4502
4503 static void R_FrameData_Resize(void)
4504 {
4505         size_t wantedsize;
4506         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4507         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4508         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4509         {
4510                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4511                 newmem->wantedsize = wantedsize;
4512                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4513                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4514                 newmem->current = 0;
4515                 newmem->mark = 0;
4516                 newmem->purge = r_framedata_mem;
4517                 r_framedata_mem = newmem;
4518         }
4519 }
4520
4521 void R_FrameData_NewFrame(void)
4522 {
4523         R_FrameData_Resize();
4524         if (!r_framedata_mem)
4525                 return;
4526         // if we ran out of space on the last frame, free the old memory now
4527         while (r_framedata_mem->purge)
4528         {
4529                 // repeatedly remove the second item in the list, leaving only head
4530                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4531                 Mem_Free(r_framedata_mem->purge);
4532                 r_framedata_mem->purge = next;
4533         }
4534         // reset the current mem pointer
4535         r_framedata_mem->current = 0;
4536         r_framedata_mem->mark = 0;
4537 }
4538
4539 void *R_FrameData_Alloc(size_t size)
4540 {
4541         void *data;
4542
4543         // align to 16 byte boundary - the data pointer is already aligned, so we
4544         // only need to ensure the size of every allocation is also aligned
4545         size = (size + 15) & ~15;
4546
4547         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4548         {
4549                 // emergency - we ran out of space, allocate more memory
4550                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4551                 R_FrameData_Resize();
4552         }
4553
4554         data = r_framedata_mem->data + r_framedata_mem->current;
4555         r_framedata_mem->current += size;
4556
4557         // count the usage for stats
4558         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4559         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4560
4561         return (void *)data;
4562 }
4563
4564 void *R_FrameData_Store(size_t size, void *data)
4565 {
4566         void *d = R_FrameData_Alloc(size);
4567         if (d && data)
4568                 memcpy(d, data, size);
4569         return d;
4570 }
4571
4572 void R_FrameData_SetMark(void)
4573 {
4574         if (!r_framedata_mem)
4575                 return;
4576         r_framedata_mem->mark = r_framedata_mem->current;
4577 }
4578
4579 void R_FrameData_ReturnToMark(void)
4580 {
4581         if (!r_framedata_mem)
4582                 return;
4583         r_framedata_mem->current = r_framedata_mem->mark;
4584 }
4585
4586 //==================================================================================
4587
4588 // LordHavoc: animcache originally written by Echon, rewritten since then
4589
4590 /**
4591  * Animation cache prevents re-generating mesh data for an animated model
4592  * multiple times in one frame for lighting, shadowing, reflections, etc.
4593  */
4594
4595 void R_AnimCache_Free(void)
4596 {
4597 }
4598
4599 void R_AnimCache_ClearCache(void)
4600 {
4601         int i;
4602         entity_render_t *ent;
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605         {
4606                 ent = r_refdef.scene.entities[i];
4607                 ent->animcache_vertex3f = NULL;
4608                 ent->animcache_normal3f = NULL;
4609                 ent->animcache_svector3f = NULL;
4610                 ent->animcache_tvector3f = NULL;
4611                 ent->animcache_vertexmesh = NULL;
4612                 ent->animcache_vertex3fbuffer = NULL;
4613                 ent->animcache_vertexmeshbuffer = NULL;
4614         }
4615 }
4616
4617 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4618 {
4619         int i;
4620
4621         // check if we need the meshbuffers
4622         if (!vid.useinterleavedarrays)
4623                 return;
4624
4625         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4626                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4627         // TODO: upload vertex3f buffer?
4628         if (ent->animcache_vertexmesh)
4629         {
4630                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4631                 for (i = 0;i < numvertices;i++)
4632                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4633                 if (ent->animcache_svector3f)
4634                         for (i = 0;i < numvertices;i++)
4635                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4636                 if (ent->animcache_tvector3f)
4637                         for (i = 0;i < numvertices;i++)
4638                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4639                 if (ent->animcache_normal3f)
4640                         for (i = 0;i < numvertices;i++)
4641                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4642                 // TODO: upload vertexmeshbuffer?
4643         }
4644 }
4645
4646 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4647 {
4648         dp_model_t *model = ent->model;
4649         int numvertices;
4650         // see if it's already cached this frame
4651         if (ent->animcache_vertex3f)
4652         {
4653                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4654                 if (wantnormals || wanttangents)
4655                 {
4656                         if (ent->animcache_normal3f)
4657                                 wantnormals = false;
4658                         if (ent->animcache_svector3f)
4659                                 wanttangents = false;
4660                         if (wantnormals || wanttangents)
4661                         {
4662                                 numvertices = model->surfmesh.num_vertices;
4663                                 if (wantnormals)
4664                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665                                 if (wanttangents)
4666                                 {
4667                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4668                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4669                                 }
4670                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4671                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4672                         }
4673                 }
4674         }
4675         else
4676         {
4677                 // see if this ent is worth caching
4678                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4679                         return false;
4680                 // get some memory for this entity and generate mesh data
4681                 numvertices = model->surfmesh.num_vertices;
4682                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4683                 if (wantnormals)
4684                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4685                 if (wanttangents)
4686                 {
4687                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4688                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4689                 }
4690                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4691                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4692         }
4693         return true;
4694 }
4695
4696 void R_AnimCache_CacheVisibleEntities(void)
4697 {
4698         int i;
4699         qboolean wantnormals = true;
4700         qboolean wanttangents = !r_showsurfaces.integer;
4701
4702         switch(vid.renderpath)
4703         {
4704         case RENDERPATH_GL20:
4705         case RENDERPATH_D3D9:
4706         case RENDERPATH_D3D10:
4707         case RENDERPATH_D3D11:
4708         case RENDERPATH_GLES2:
4709                 break;
4710         case RENDERPATH_GL11:
4711         case RENDERPATH_GL13:
4712         case RENDERPATH_GLES1:
4713                 wanttangents = false;
4714                 break;
4715         case RENDERPATH_SOFT:
4716                 break;
4717         }
4718
4719         if (r_shownormals.integer)
4720                 wanttangents = wantnormals = true;
4721
4722         // TODO: thread this
4723         // NOTE: R_PrepareRTLights() also caches entities
4724
4725         for (i = 0;i < r_refdef.scene.numentities;i++)
4726                 if (r_refdef.viewcache.entityvisible[i])
4727                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4728 }
4729
4730 //==================================================================================
4731
4732 extern cvar_t r_overheadsprites_pushback;
4733
4734 static void R_View_UpdateEntityLighting (void)
4735 {
4736         int i;
4737         entity_render_t *ent;
4738         vec3_t tempdiffusenormal, avg;
4739         vec_t f, fa, fd, fdd;
4740         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4741
4742         for (i = 0;i < r_refdef.scene.numentities;i++)
4743         {
4744                 ent = r_refdef.scene.entities[i];
4745
4746                 // skip unseen models
4747                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4748                         continue;
4749
4750                 // skip bsp models
4751                 if (ent->model && ent->model == cl.worldmodel)
4752                 {
4753                         // TODO: use modellight for r_ambient settings on world?
4754                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4755                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4756                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4757                         continue;
4758                 }
4759                 
4760                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4761                 {
4762                         // aleady updated by CSQC
4763                         // TODO: force modellight on BSP models in this case?
4764                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4765                 }
4766                 else
4767                 {
4768                         // fetch the lighting from the worldmodel data
4769                         VectorClear(ent->modellight_ambient);
4770                         VectorClear(ent->modellight_diffuse);
4771                         VectorClear(tempdiffusenormal);
4772                         if (ent->flags & RENDER_LIGHT)
4773                         {
4774                                 vec3_t org;
4775                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4776
4777                                 // complete lightning for lit sprites
4778                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4779                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4780                                 {
4781                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4782                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4783                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4784                                 }
4785                                 else
4786                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4787
4788                                 if(ent->flags & RENDER_EQUALIZE)
4789                                 {
4790                                         // first fix up ambient lighting...
4791                                         if(r_equalize_entities_minambient.value > 0)
4792                                         {
4793                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4794                                                 if(fd > 0)
4795                                                 {
4796                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4797                                                         if(fa < r_equalize_entities_minambient.value * fd)
4798                                                         {
4799                                                                 // solve:
4800                                                                 //   fa'/fd' = minambient
4801                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4802                                                                 //   ...
4803                                                                 //   fa' = fd' * minambient
4804                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4805                                                                 //   ...
4806                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4807                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4808                                                                 //   ...
4809                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4810                                                                 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4811                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4812                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4813                                                         }
4814                                                 }
4815                                         }
4816
4817                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4818                                         {
4819                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4820                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4821                                                 f = fa + 0.25 * fd;
4822                                                 if(f > 0)
4823                                                 {
4824                                                         // adjust brightness and saturation to target
4825                                                         avg[0] = avg[1] = avg[2] = fa / f;
4826                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4827                                                         avg[0] = avg[1] = avg[2] = fd / f;
4828                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4829                                                 }
4830                                         }
4831                                 }
4832                         }
4833                         else // highly rare
4834                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4835                 }
4836
4837                 // move the light direction into modelspace coordinates for lighting code
4838                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4839                 if(VectorLength2(ent->modellight_lightdir) == 0)
4840                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4841                 VectorNormalize(ent->modellight_lightdir);
4842         }
4843 }
4844
4845 #define MAX_LINEOFSIGHTTRACES 64
4846
4847 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4848 {
4849         int i;
4850         vec3_t boxmins, boxmaxs;
4851         vec3_t start;
4852         vec3_t end;
4853         dp_model_t *model = r_refdef.scene.worldmodel;
4854
4855         if (!model || !model->brush.TraceLineOfSight)
4856                 return true;
4857
4858         // expand the box a little
4859         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4860         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4861         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4862         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4863         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4864         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4865
4866         // return true if eye is inside enlarged box
4867         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4868                 return true;
4869
4870         // try center
4871         VectorCopy(eye, start);
4872         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4873         if (model->brush.TraceLineOfSight(model, start, end))
4874                 return true;
4875
4876         // try various random positions
4877         for (i = 0;i < numsamples;i++)
4878         {
4879                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4880                 if (model->brush.TraceLineOfSight(model, start, end))
4881                         return true;
4882         }
4883
4884         return false;
4885 }
4886
4887
4888 static void R_View_UpdateEntityVisible (void)
4889 {
4890         int i;
4891         int renderimask;
4892         int samples;
4893         entity_render_t *ent;
4894
4895         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4896                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4897                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4898                 :                                                          RENDER_EXTERIORMODEL;
4899         if (!r_drawviewmodel.integer)
4900                 renderimask |= RENDER_VIEWMODEL;
4901         if (!r_drawexteriormodel.integer)
4902                 renderimask |= RENDER_EXTERIORMODEL;
4903         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4904         {
4905                 // worldmodel can check visibility
4906                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         ent = r_refdef.scene.entities[i];
4910                         if (!(ent->flags & renderimask))
4911                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4912                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4913                                 r_refdef.viewcache.entityvisible[i] = true;
4914                 }
4915         }
4916         else
4917         {
4918                 // no worldmodel or it can't check visibility
4919                 for (i = 0;i < r_refdef.scene.numentities;i++)
4920                 {
4921                         ent = r_refdef.scene.entities[i];
4922                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4923                 }
4924         }
4925         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4926                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4927         {
4928                 for (i = 0;i < r_refdef.scene.numentities;i++)
4929                 {
4930                         if (!r_refdef.viewcache.entityvisible[i])
4931                                 continue;
4932                         ent = r_refdef.scene.entities[i];
4933                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4934                         {
4935                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4936                                 if (samples < 0)
4937                                         continue; // temp entities do pvs only
4938                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4939                                         ent->last_trace_visibility = realtime;
4940                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4941                                         r_refdef.viewcache.entityvisible[i] = 0;
4942                         }
4943                 }
4944         }
4945 }
4946
4947 /// only used if skyrendermasked, and normally returns false
4948 static int R_DrawBrushModelsSky (void)
4949 {
4950         int i, sky;
4951         entity_render_t *ent;
4952
4953         sky = false;
4954         for (i = 0;i < r_refdef.scene.numentities;i++)
4955         {
4956                 if (!r_refdef.viewcache.entityvisible[i])
4957                         continue;
4958                 ent = r_refdef.scene.entities[i];
4959                 if (!ent->model || !ent->model->DrawSky)
4960                         continue;
4961                 ent->model->DrawSky(ent);
4962                 sky = true;
4963         }
4964         return sky;
4965 }
4966
4967 static void R_DrawNoModel(entity_render_t *ent);
4968 static void R_DrawModels(void)
4969 {
4970         int i;
4971         entity_render_t *ent;
4972
4973         for (i = 0;i < r_refdef.scene.numentities;i++)
4974         {
4975                 if (!r_refdef.viewcache.entityvisible[i])
4976                         continue;
4977                 ent = r_refdef.scene.entities[i];
4978                 r_refdef.stats.entities++;
4979                 /*
4980                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4981                 {
4982                         vec3_t f, l, u, o;
4983                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4984                         Con_Printf("R_DrawModels\n");
4985                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4986                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4987                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4988                 }
4989                 */
4990                 if (ent->model && ent->model->Draw != NULL)
4991                         ent->model->Draw(ent);
4992                 else
4993                         R_DrawNoModel(ent);
4994         }
4995 }
4996
4997 static void R_DrawModelsDepth(void)
4998 {
4999         int i;
5000         entity_render_t *ent;
5001
5002         for (i = 0;i < r_refdef.scene.numentities;i++)
5003         {
5004                 if (!r_refdef.viewcache.entityvisible[i])
5005                         continue;
5006                 ent = r_refdef.scene.entities[i];
5007                 if (ent->model && ent->model->DrawDepth != NULL)
5008                         ent->model->DrawDepth(ent);
5009         }
5010 }
5011
5012 static void R_DrawModelsDebug(void)
5013 {
5014         int i;
5015         entity_render_t *ent;
5016
5017         for (i = 0;i < r_refdef.scene.numentities;i++)
5018         {
5019                 if (!r_refdef.viewcache.entityvisible[i])
5020                         continue;
5021                 ent = r_refdef.scene.entities[i];
5022                 if (ent->model && ent->model->DrawDebug != NULL)
5023                         ent->model->DrawDebug(ent);
5024         }
5025 }
5026
5027 static void R_DrawModelsAddWaterPlanes(void)
5028 {
5029         int i;
5030         entity_render_t *ent;
5031
5032         for (i = 0;i < r_refdef.scene.numentities;i++)
5033         {
5034                 if (!r_refdef.viewcache.entityvisible[i])
5035                         continue;
5036                 ent = r_refdef.scene.entities[i];
5037                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5038                         ent->model->DrawAddWaterPlanes(ent);
5039         }
5040 }
5041
5042 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5043
5044 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5045 {
5046         if (r_hdr_irisadaptation.integer)
5047         {
5048                 vec3_t p;
5049                 vec3_t ambient;
5050                 vec3_t diffuse;
5051                 vec3_t diffusenormal;
5052                 vec3_t forward;
5053                 vec_t brightness = 0.0f;
5054                 vec_t goal;
5055                 vec_t current;
5056                 vec_t d;
5057                 int c;
5058                 VectorCopy(r_refdef.view.forward, forward);
5059                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5060                 {
5061                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5062                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5063                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5064                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5065                         d = DotProduct(forward, diffusenormal);
5066                         brightness += VectorLength(ambient);
5067                         if (d > 0)
5068                                 brightness += d * VectorLength(diffuse);
5069                 }
5070                 brightness *= 1.0f / c;
5071                 brightness += 0.00001f; // make sure it's never zero
5072                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5073                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5074                 current = r_hdr_irisadaptation_value.value;
5075                 if (current < goal)
5076                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5077                 else if (current > goal)
5078                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5079                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5080                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5081         }
5082         else if (r_hdr_irisadaptation_value.value != 1.0f)
5083                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5084 }
5085
5086 static void R_View_SetFrustum(const int *scissor)
5087 {
5088         int i;
5089         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5090         vec3_t forward, left, up, origin, v;
5091
5092         if(scissor)
5093         {
5094                 // flipped x coordinates (because x points left here)
5095                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5096                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5097
5098                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5099                 switch(vid.renderpath)
5100                 {
5101                         case RENDERPATH_D3D9:
5102                         case RENDERPATH_D3D10:
5103                         case RENDERPATH_D3D11:
5104                                 // non-flipped y coordinates
5105                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5106                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5107                                 break;
5108                         case RENDERPATH_SOFT:
5109                         case RENDERPATH_GL11:
5110                         case RENDERPATH_GL13:
5111                         case RENDERPATH_GL20:
5112                         case RENDERPATH_GLES1:
5113                         case RENDERPATH_GLES2:
5114                                 // non-flipped y coordinates
5115                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5117                                 break;
5118                 }
5119         }
5120
5121         // we can't trust r_refdef.view.forward and friends in reflected scenes
5122         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5123
5124 #if 0
5125         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5126         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5127         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5128         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5129         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5130         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5131         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5132         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5133         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5134         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5135         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5136         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5137 #endif
5138
5139 #if 0
5140         zNear = r_refdef.nearclip;
5141         nudge = 1.0 - 1.0 / (1<<23);
5142         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5143         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5144         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5145         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5146         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5147         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5148         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5149         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5150 #endif
5151
5152
5153
5154 #if 0
5155         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5156         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5157         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5158         r_refdef.view.frustum[0].dist = m[15] - m[12];
5159
5160         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5161         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5162         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5163         r_refdef.view.frustum[1].dist = m[15] + m[12];
5164
5165         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5166         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5167         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5168         r_refdef.view.frustum[2].dist = m[15] - m[13];
5169
5170         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5171         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5172         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5173         r_refdef.view.frustum[3].dist = m[15] + m[13];
5174
5175         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5176         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5177         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5178         r_refdef.view.frustum[4].dist = m[15] - m[14];
5179
5180         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5181         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5182         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5183         r_refdef.view.frustum[5].dist = m[15] + m[14];
5184 #endif
5185
5186         if (r_refdef.view.useperspective)
5187         {
5188                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5189                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5190                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5191                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5192                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5193
5194                 // then the normals from the corners relative to origin
5195                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5196                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5197                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5198                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5199
5200                 // in a NORMAL view, forward cross left == up
5201                 // in a REFLECTED view, forward cross left == down
5202                 // so our cross products above need to be adjusted for a left handed coordinate system
5203                 CrossProduct(forward, left, v);
5204                 if(DotProduct(v, up) < 0)
5205                 {
5206                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5207                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5208                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5209                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5210                 }
5211
5212                 // Leaving those out was a mistake, those were in the old code, and they
5213                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5214                 // I couldn't reproduce it after adding those normalizations. --blub
5215                 VectorNormalize(r_refdef.view.frustum[0].normal);
5216                 VectorNormalize(r_refdef.view.frustum[1].normal);
5217                 VectorNormalize(r_refdef.view.frustum[2].normal);
5218                 VectorNormalize(r_refdef.view.frustum[3].normal);
5219
5220                 // make the corners absolute
5221                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5222                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5223                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5224                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5225
5226                 // one more normal
5227                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5228
5229                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5230                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5231                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5232                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5233                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5234         }
5235         else
5236         {
5237                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5238                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5239                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5240                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5241                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5242                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5243                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5244                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5245                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5246                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5247         }
5248         r_refdef.view.numfrustumplanes = 5;
5249
5250         if (r_refdef.view.useclipplane)
5251         {
5252                 r_refdef.view.numfrustumplanes = 6;
5253                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5254         }
5255
5256         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5257                 PlaneClassify(r_refdef.view.frustum + i);
5258
5259         // LordHavoc: note to all quake engine coders, Quake had a special case
5260         // for 90 degrees which assumed a square view (wrong), so I removed it,
5261         // Quake2 has it disabled as well.
5262
5263         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5264         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5265         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5266         //PlaneClassify(&frustum[0]);
5267
5268         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5269         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5270         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5271         //PlaneClassify(&frustum[1]);
5272
5273         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5274         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5275         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5276         //PlaneClassify(&frustum[2]);
5277
5278         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5279         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5280         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5281         //PlaneClassify(&frustum[3]);
5282
5283         // nearclip plane
5284         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5285         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5286         //PlaneClassify(&frustum[4]);
5287 }
5288
5289 static void R_View_UpdateWithScissor(const int *myscissor)
5290 {
5291         R_Main_ResizeViewCache();
5292         R_View_SetFrustum(myscissor);
5293         R_View_WorldVisibility(r_refdef.view.useclipplane);
5294         R_View_UpdateEntityVisible();
5295         R_View_UpdateEntityLighting();
5296 }
5297
5298 static void R_View_Update(void)
5299 {
5300         R_Main_ResizeViewCache();
5301         R_View_SetFrustum(NULL);
5302         R_View_WorldVisibility(r_refdef.view.useclipplane);
5303         R_View_UpdateEntityVisible();
5304         R_View_UpdateEntityLighting();
5305 }
5306
5307 float viewscalefpsadjusted = 1.0f;
5308
5309 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5310 {
5311         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5312         scale = bound(0.03125f, scale, 1.0f);
5313         *outwidth = (int)ceil(width * scale);
5314         *outheight = (int)ceil(height * scale);
5315 }
5316
5317 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5318 {
5319         const float *customclipplane = NULL;
5320         float plane[4];
5321         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5322         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5323         {
5324                 // LordHavoc: couldn't figure out how to make this approach the
5325                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5326                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5327                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5328                         dist = r_refdef.view.clipplane.dist;
5329                 plane[0] = r_refdef.view.clipplane.normal[0];
5330                 plane[1] = r_refdef.view.clipplane.normal[1];
5331                 plane[2] = r_refdef.view.clipplane.normal[2];
5332                 plane[3] = -dist;
5333                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5334         }
5335
5336         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5337         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5338
5339         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5340         if (!r_refdef.view.useperspective)
5341                 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);
5342         else if (vid.stencil && r_useinfinitefarclip.integer)
5343                 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);
5344         else
5345                 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);
5346         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5347         R_SetViewport(&r_refdef.view.viewport);
5348         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5349         {
5350                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5351                 float screenplane[4];
5352                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5353                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5354                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5355                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5356                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5357         }
5358 }
5359
5360 void R_EntityMatrix(const matrix4x4_t *matrix)
5361 {
5362         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5363         {
5364                 gl_modelmatrixchanged = false;
5365                 gl_modelmatrix = *matrix;
5366                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5367                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5368                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5369                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5370                 CHECKGLERROR
5371                 switch(vid.renderpath)
5372                 {
5373                 case RENDERPATH_D3D9:
5374 #ifdef SUPPORTD3D
5375                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5376                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5377 #endif
5378                         break;
5379                 case RENDERPATH_D3D10:
5380                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5381                         break;
5382                 case RENDERPATH_D3D11:
5383                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5384                         break;
5385                 case RENDERPATH_GL11:
5386                 case RENDERPATH_GL13:
5387                 case RENDERPATH_GLES1:
5388                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5389                         break;
5390                 case RENDERPATH_SOFT:
5391                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5392                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5393                         break;
5394                 case RENDERPATH_GL20:
5395                 case RENDERPATH_GLES2:
5396                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5397                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5398                         break;
5399                 }
5400         }
5401 }
5402
5403 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5404 {
5405         r_viewport_t viewport;
5406
5407         CHECKGLERROR
5408
5409         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5410         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);
5411         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5412         R_SetViewport(&viewport);
5413         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5414         GL_Color(1, 1, 1, 1);
5415         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5416         GL_BlendFunc(GL_ONE, GL_ZERO);
5417         GL_ScissorTest(false);
5418         GL_DepthMask(false);
5419         GL_DepthRange(0, 1);
5420         GL_DepthTest(false);
5421         GL_DepthFunc(GL_LEQUAL);
5422         R_EntityMatrix(&identitymatrix);
5423         R_Mesh_ResetTextureState();
5424         GL_PolygonOffset(0, 0);
5425         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5426         switch(vid.renderpath)
5427         {
5428         case RENDERPATH_GL11:
5429         case RENDERPATH_GL13:
5430         case RENDERPATH_GL20:
5431         case RENDERPATH_GLES1:
5432         case RENDERPATH_GLES2:
5433                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5434                 break;
5435         case RENDERPATH_D3D9:
5436         case RENDERPATH_D3D10:
5437         case RENDERPATH_D3D11:
5438         case RENDERPATH_SOFT:
5439                 break;
5440         }
5441         GL_CullFace(GL_NONE);
5442
5443         CHECKGLERROR
5444 }
5445
5446 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5447 {
5448         DrawQ_Finish();
5449
5450         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5451 }
5452
5453 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5454 {
5455         DrawQ_Finish();
5456
5457         R_SetupView(true, fbo, depthtexture, colortexture);
5458         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5459         GL_Color(1, 1, 1, 1);
5460         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5461         GL_BlendFunc(GL_ONE, GL_ZERO);
5462         GL_ScissorTest(true);
5463         GL_DepthMask(true);
5464         GL_DepthRange(0, 1);
5465         GL_DepthTest(true);
5466         GL_DepthFunc(GL_LEQUAL);
5467         R_EntityMatrix(&identitymatrix);
5468         R_Mesh_ResetTextureState();
5469         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5470         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5471         switch(vid.renderpath)
5472         {
5473         case RENDERPATH_GL11:
5474         case RENDERPATH_GL13:
5475         case RENDERPATH_GL20:
5476         case RENDERPATH_GLES1:
5477         case RENDERPATH_GLES2:
5478                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5479                 break;
5480         case RENDERPATH_D3D9:
5481         case RENDERPATH_D3D10:
5482         case RENDERPATH_D3D11:
5483         case RENDERPATH_SOFT:
5484                 break;
5485         }
5486         GL_CullFace(r_refdef.view.cullface_back);
5487 }
5488
5489 /*
5490 ================
5491 R_RenderView_UpdateViewVectors
5492 ================
5493 */
5494 void R_RenderView_UpdateViewVectors(void)
5495 {
5496         // break apart the view matrix into vectors for various purposes
5497         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5498         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5499         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5500         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5501         // make an inverted copy of the view matrix for tracking sprites
5502         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5503 }
5504
5505 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5506 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5507
5508 static void R_Water_StartFrame(void)
5509 {
5510         int i;
5511         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5512         r_waterstate_waterplane_t *p;
5513         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5514
5515         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5516                 return;
5517
5518         switch(vid.renderpath)
5519         {
5520         case RENDERPATH_GL20:
5521         case RENDERPATH_D3D9:
5522         case RENDERPATH_D3D10:
5523         case RENDERPATH_D3D11:
5524         case RENDERPATH_SOFT:
5525         case RENDERPATH_GLES2:
5526                 break;
5527         case RENDERPATH_GL11:
5528         case RENDERPATH_GL13:
5529         case RENDERPATH_GLES1:
5530                 return;
5531         }
5532
5533         // set waterwidth and waterheight to the water resolution that will be
5534         // used (often less than the screen resolution for faster rendering)
5535         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5536
5537         // calculate desired texture sizes
5538         // can't use water if the card does not support the texture size
5539         if (!r_water.integer || r_showsurfaces.integer)
5540                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5541         else if (vid.support.arb_texture_non_power_of_two)
5542         {
5543                 texturewidth = waterwidth;
5544                 textureheight = waterheight;
5545                 camerawidth = waterwidth;
5546                 cameraheight = waterheight;
5547         }
5548         else
5549         {
5550                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5551                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5552                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5553                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5554         }
5555
5556         // allocate textures as needed
5557         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))
5558         {
5559                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5560                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5561                 {
5562                         if (p->texture_refraction)
5563                                 R_FreeTexture(p->texture_refraction);
5564                         p->texture_refraction = NULL;
5565                         if (p->fbo_refraction)
5566                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5567                         p->fbo_refraction = 0;
5568                         if (p->texture_reflection)
5569                                 R_FreeTexture(p->texture_reflection);
5570                         p->texture_reflection = NULL;
5571                         if (p->fbo_reflection)
5572                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5573                         p->fbo_reflection = 0;
5574                         if (p->texture_camera)
5575                                 R_FreeTexture(p->texture_camera);
5576                         p->texture_camera = NULL;
5577                         if (p->fbo_camera)
5578                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5579                         p->fbo_camera = 0;
5580                 }
5581                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5582                 r_fb.water.texturewidth = texturewidth;
5583                 r_fb.water.textureheight = textureheight;
5584                 r_fb.water.camerawidth = camerawidth;
5585                 r_fb.water.cameraheight = cameraheight;
5586         }
5587
5588         if (r_fb.water.texturewidth)
5589         {
5590                 int scaledwidth, scaledheight;
5591
5592                 r_fb.water.enabled = true;
5593
5594                 // water resolution is usually reduced
5595                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5596                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5597                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5598
5599                 // set up variables that will be used in shader setup
5600                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5601                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5602                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5603                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5604         }
5605
5606         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5607         r_fb.water.numwaterplanes = 0;
5608 }
5609
5610 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5611 {
5612         int planeindex, bestplaneindex, vertexindex;
5613         vec3_t mins, maxs, normal, center, v, n;
5614         vec_t planescore, bestplanescore;
5615         mplane_t plane;
5616         r_waterstate_waterplane_t *p;
5617         texture_t *t = R_GetCurrentTexture(surface->texture);
5618
5619         rsurface.texture = t;
5620         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5621         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5622         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5623                 return;
5624         // average the vertex normals, find the surface bounds (after deformvertexes)
5625         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5626         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5627         VectorCopy(n, normal);
5628         VectorCopy(v, mins);
5629         VectorCopy(v, maxs);
5630         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5631         {
5632                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5633                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5634                 VectorAdd(normal, n, normal);
5635                 mins[0] = min(mins[0], v[0]);
5636                 mins[1] = min(mins[1], v[1]);
5637                 mins[2] = min(mins[2], v[2]);
5638                 maxs[0] = max(maxs[0], v[0]);
5639                 maxs[1] = max(maxs[1], v[1]);
5640                 maxs[2] = max(maxs[2], v[2]);
5641         }
5642         VectorNormalize(normal);
5643         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5644
5645         VectorCopy(normal, plane.normal);
5646         VectorNormalize(plane.normal);
5647         plane.dist = DotProduct(center, plane.normal);
5648         PlaneClassify(&plane);
5649         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5650         {
5651                 // skip backfaces (except if nocullface is set)
5652 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5653 //                      return;
5654                 VectorNegate(plane.normal, plane.normal);
5655                 plane.dist *= -1;
5656                 PlaneClassify(&plane);
5657         }
5658
5659
5660         // find a matching plane if there is one
5661         bestplaneindex = -1;
5662         bestplanescore = 1048576.0f;
5663         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5664         {
5665                 if(p->camera_entity == t->camera_entity)
5666                 {
5667                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5668                         if (bestplaneindex < 0 || bestplanescore > planescore)
5669                         {
5670                                 bestplaneindex = planeindex;
5671                                 bestplanescore = planescore;
5672                         }
5673                 }
5674         }
5675         planeindex = bestplaneindex;
5676         p = r_fb.water.waterplanes + planeindex;
5677
5678         // if this surface does not fit any known plane rendered this frame, add one
5679         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5680         {
5681                 // store the new plane
5682                 planeindex = r_fb.water.numwaterplanes++;
5683                 p = r_fb.water.waterplanes + planeindex;
5684                 p->plane = plane;
5685                 // clear materialflags and pvs
5686                 p->materialflags = 0;
5687                 p->pvsvalid = false;
5688                 p->camera_entity = t->camera_entity;
5689                 VectorCopy(mins, p->mins);
5690                 VectorCopy(maxs, p->maxs);
5691         }
5692         else
5693         {
5694                 // merge mins/maxs when we're adding this surface to the plane
5695                 p->mins[0] = min(p->mins[0], mins[0]);
5696                 p->mins[1] = min(p->mins[1], mins[1]);
5697                 p->mins[2] = min(p->mins[2], mins[2]);
5698                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5699                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5700                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5701         }
5702         // merge this surface's materialflags into the waterplane
5703         p->materialflags |= t->currentmaterialflags;
5704         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5705         {
5706                 // merge this surface's PVS into the waterplane
5707                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5708                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5709                 {
5710                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5711                         p->pvsvalid = true;
5712                 }
5713         }
5714 }
5715
5716 extern cvar_t r_drawparticles;
5717 extern cvar_t r_drawdecals;
5718
5719 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5720 {
5721         int myscissor[4];
5722         r_refdef_view_t originalview;
5723         r_refdef_view_t myview;
5724         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;
5725         r_waterstate_waterplane_t *p;
5726         vec3_t visorigin;
5727         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5728         char vabuf[1024];
5729
5730         originalview = r_refdef.view;
5731
5732         // lowquality hack, temporarily shut down some cvars and restore afterwards
5733         qualityreduction = r_water_lowquality.integer;
5734         if (qualityreduction > 0)
5735         {
5736                 if (qualityreduction >= 1)
5737                 {
5738                         old_r_shadows = r_shadows.integer;
5739                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5740                         old_r_dlight = r_shadow_realtime_dlight.integer;
5741                         Cvar_SetValueQuick(&r_shadows, 0);
5742                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5743                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5744                 }
5745                 if (qualityreduction >= 2)
5746                 {
5747                         old_r_dynamic = r_dynamic.integer;
5748                         old_r_particles = r_drawparticles.integer;
5749                         old_r_decals = r_drawdecals.integer;
5750                         Cvar_SetValueQuick(&r_dynamic, 0);
5751                         Cvar_SetValueQuick(&r_drawparticles, 0);
5752                         Cvar_SetValueQuick(&r_drawdecals, 0);
5753                 }
5754         }
5755
5756         // make sure enough textures are allocated
5757         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5758         {
5759                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5760                 {
5761                         if (!p->texture_refraction)
5762                                 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);
5763                         if (!p->texture_refraction)
5764                                 goto error;
5765                         if (usewaterfbo)
5766                         {
5767                                 if (r_fb.water.depthtexture == NULL)
5768                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5769                                 if (p->fbo_refraction == 0)
5770                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5771                         }
5772                 }
5773                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5774                 {
5775                         if (!p->texture_camera)
5776                                 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);
5777                         if (!p->texture_camera)
5778                                 goto error;
5779                         if (usewaterfbo)
5780                         {
5781                                 if (r_fb.water.depthtexture == NULL)
5782                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5783                                 if (p->fbo_camera == 0)
5784                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5785                         }
5786                 }
5787
5788                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5789                 {
5790                         if (!p->texture_reflection)
5791                                 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);
5792                         if (!p->texture_reflection)
5793                                 goto error;
5794                         if (usewaterfbo)
5795                         {
5796                                 if (r_fb.water.depthtexture == NULL)
5797                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5798                                 if (p->fbo_reflection == 0)
5799                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5800                         }
5801                 }
5802         }
5803
5804         // render views
5805         r_refdef.view = originalview;
5806         r_refdef.view.showdebug = false;
5807         r_refdef.view.width = r_fb.water.waterwidth;
5808         r_refdef.view.height = r_fb.water.waterheight;
5809         r_refdef.view.useclipplane = true;
5810         myview = r_refdef.view;
5811         r_fb.water.renderingscene = true;
5812         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5813         {
5814                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5815                 {
5816                         r_refdef.view = myview;
5817                         if(r_water_scissormode.integer)
5818                         {
5819                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5820                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5821                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5822                         }
5823
5824                         // render reflected scene and copy into texture
5825                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5826                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5827                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5828                         r_refdef.view.clipplane = p->plane;
5829                         // reverse the cullface settings for this render
5830                         r_refdef.view.cullface_front = GL_FRONT;
5831                         r_refdef.view.cullface_back = GL_BACK;
5832                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5833                         {
5834                                 r_refdef.view.usecustompvs = true;
5835                                 if (p->pvsvalid)
5836                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5837                                 else
5838                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5839                         }
5840
5841                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5842                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5843                         R_ClearScreen(r_refdef.fogenabled);
5844                         if(r_water_scissormode.integer & 2)
5845                                 R_View_UpdateWithScissor(myscissor);
5846                         else
5847                                 R_View_Update();
5848                         R_AnimCache_CacheVisibleEntities();
5849                         if(r_water_scissormode.integer & 1)
5850                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5851                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5852
5853                         if (!p->fbo_reflection)
5854                                 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);
5855                         r_fb.water.hideplayer = false;
5856                 }
5857
5858                 // render the normal view scene and copy into texture
5859                 // (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)
5860                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5861                 {
5862                         r_refdef.view = myview;
5863                         if(r_water_scissormode.integer)
5864                         {
5865                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5866                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5867                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5868                         }
5869
5870                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5871
5872                         r_refdef.view.clipplane = p->plane;
5873                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5874                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5875
5876                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5877                         {
5878                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5879                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5880                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5881                                 R_RenderView_UpdateViewVectors();
5882                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5883                                 {
5884                                         r_refdef.view.usecustompvs = true;
5885                                         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);
5886                                 }
5887                         }
5888
5889                         PlaneClassify(&r_refdef.view.clipplane);
5890
5891                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5892                         R_ClearScreen(r_refdef.fogenabled);
5893                         if(r_water_scissormode.integer & 2)
5894                                 R_View_UpdateWithScissor(myscissor);
5895                         else
5896                                 R_View_Update();
5897                         R_AnimCache_CacheVisibleEntities();
5898                         if(r_water_scissormode.integer & 1)
5899                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5900                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5901
5902                         if (!p->fbo_refraction)
5903                                 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5904                         r_fb.water.hideplayer = false;
5905                 }
5906                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5907                 {
5908                         r_refdef.view = myview;
5909
5910                         r_refdef.view.clipplane = p->plane;
5911                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5912                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5913
5914                         r_refdef.view.width = r_fb.water.camerawidth;
5915                         r_refdef.view.height = r_fb.water.cameraheight;
5916                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5917                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5918                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5919                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5920
5921                         if(p->camera_entity)
5922                         {
5923                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5924                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5925                         }
5926
5927                         // note: all of the view is used for displaying... so
5928                         // there is no use in scissoring
5929
5930                         // reverse the cullface settings for this render
5931                         r_refdef.view.cullface_front = GL_FRONT;
5932                         r_refdef.view.cullface_back = GL_BACK;
5933                         // also reverse the view matrix
5934                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5935                         R_RenderView_UpdateViewVectors();
5936                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5937                         {
5938                                 r_refdef.view.usecustompvs = true;
5939                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5940                         }
5941                         
5942                         // camera needs no clipplane
5943                         r_refdef.view.useclipplane = false;
5944
5945                         PlaneClassify(&r_refdef.view.clipplane);
5946
5947                         r_fb.water.hideplayer = false;
5948
5949                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5950                         R_ClearScreen(r_refdef.fogenabled);
5951                         R_View_Update();
5952                         R_AnimCache_CacheVisibleEntities();
5953                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5954
5955                         if (!p->fbo_camera)
5956                                 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);
5957                         r_fb.water.hideplayer = false;
5958                 }
5959
5960         }
5961         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5962         r_fb.water.renderingscene = false;
5963         r_refdef.view = originalview;
5964         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5965         if (!r_fb.water.depthtexture)
5966                 R_ClearScreen(r_refdef.fogenabled);
5967         R_View_Update();
5968         R_AnimCache_CacheVisibleEntities();
5969         goto finish;
5970 error:
5971         r_refdef.view = originalview;
5972         r_fb.water.renderingscene = false;
5973         Cvar_SetValueQuick(&r_water, 0);
5974         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5975 finish:
5976         // lowquality hack, restore cvars
5977         if (qualityreduction > 0)
5978         {
5979                 if (qualityreduction >= 1)
5980                 {
5981                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5982                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5983                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5984                 }
5985                 if (qualityreduction >= 2)
5986                 {
5987                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5988                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5989                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5990                 }
5991         }
5992 }
5993
5994 static void R_Bloom_StartFrame(void)
5995 {
5996         int i;
5997         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5998         int viewwidth, viewheight;
5999         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6000         textype_t textype = TEXTYPE_COLORBUFFER;
6001
6002         switch (vid.renderpath)
6003         {
6004         case RENDERPATH_GL20:
6005                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6006                 if (vid.support.ext_framebuffer_object)
6007                 {
6008                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6009                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6010                 }
6011                 break;
6012         case RENDERPATH_GL11:
6013         case RENDERPATH_GL13:
6014         case RENDERPATH_GLES1:
6015         case RENDERPATH_GLES2:
6016         case RENDERPATH_D3D9:
6017         case RENDERPATH_D3D10:
6018         case RENDERPATH_D3D11:
6019                 r_fb.usedepthtextures = false;
6020                 break;
6021         case RENDERPATH_SOFT:
6022                 r_fb.usedepthtextures = true;
6023                 break;
6024         }
6025
6026         if (r_viewscale_fpsscaling.integer)
6027         {
6028                 double actualframetime;
6029                 double targetframetime;
6030                 double adjust;
6031                 actualframetime = r_refdef.lastdrawscreentime;
6032                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6033                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6034                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6035                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6036                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6037                 viewscalefpsadjusted += adjust;
6038                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6039         }
6040         else
6041                 viewscalefpsadjusted = 1.0f;
6042
6043         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6044
6045         switch(vid.renderpath)
6046         {
6047         case RENDERPATH_GL20:
6048         case RENDERPATH_D3D9:
6049         case RENDERPATH_D3D10:
6050         case RENDERPATH_D3D11:
6051         case RENDERPATH_SOFT:
6052         case RENDERPATH_GLES2:
6053                 break;
6054         case RENDERPATH_GL11:
6055         case RENDERPATH_GL13:
6056         case RENDERPATH_GLES1:
6057                 return;
6058         }
6059
6060         // set bloomwidth and bloomheight to the bloom resolution that will be
6061         // used (often less than the screen resolution for faster rendering)
6062         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6063         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6064         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6065         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6066         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6067
6068         // calculate desired texture sizes
6069         if (vid.support.arb_texture_non_power_of_two)
6070         {
6071                 screentexturewidth = vid.width;
6072                 screentextureheight = vid.height;
6073                 bloomtexturewidth = r_fb.bloomwidth;
6074                 bloomtextureheight = r_fb.bloomheight;
6075         }
6076         else
6077         {
6078                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6079                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6080                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6081                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6082         }
6083
6084         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))
6085         {
6086                 Cvar_SetValueQuick(&r_bloom, 0);
6087                 Cvar_SetValueQuick(&r_motionblur, 0);
6088                 Cvar_SetValueQuick(&r_damageblur, 0);
6089         }
6090
6091         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6092          && !r_bloom.integer
6093          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6094          && !useviewfbo
6095          && r_viewscale.value == 1.0f
6096          && !r_viewscale_fpsscaling.integer)
6097                 screentexturewidth = screentextureheight = 0;
6098         if (!r_bloom.integer)
6099                 bloomtexturewidth = bloomtextureheight = 0;
6100
6101         // allocate textures as needed
6102         if (r_fb.screentexturewidth != screentexturewidth
6103          || r_fb.screentextureheight != screentextureheight
6104          || r_fb.bloomtexturewidth != bloomtexturewidth
6105          || r_fb.bloomtextureheight != bloomtextureheight
6106          || r_fb.textype != textype
6107          || useviewfbo != (r_fb.fbo != 0))
6108         {
6109                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6110                 {
6111                         if (r_fb.bloomtexture[i])
6112                                 R_FreeTexture(r_fb.bloomtexture[i]);
6113                         r_fb.bloomtexture[i] = NULL;
6114
6115                         if (r_fb.bloomfbo[i])
6116                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6117                         r_fb.bloomfbo[i] = 0;
6118                 }
6119
6120                 if (r_fb.fbo)
6121                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6122                 r_fb.fbo = 0;
6123
6124                 if (r_fb.colortexture)
6125                         R_FreeTexture(r_fb.colortexture);
6126                 r_fb.colortexture = NULL;
6127
6128                 if (r_fb.depthtexture)
6129                         R_FreeTexture(r_fb.depthtexture);
6130                 r_fb.depthtexture = NULL;
6131
6132                 if (r_fb.ghosttexture)
6133                         R_FreeTexture(r_fb.ghosttexture);
6134                 r_fb.ghosttexture = NULL;
6135
6136                 r_fb.screentexturewidth = screentexturewidth;
6137                 r_fb.screentextureheight = screentextureheight;
6138                 r_fb.bloomtexturewidth = bloomtexturewidth;
6139                 r_fb.bloomtextureheight = bloomtextureheight;
6140                 r_fb.textype = textype;
6141
6142                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6143                 {
6144                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6145                                 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);
6146                         r_fb.ghosttexture_valid = false;
6147                         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);
6148                         if (useviewfbo)
6149                         {
6150                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6151                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6152                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6153                         }
6154                 }
6155
6156                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6157                 {
6158                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6159                         {
6160                                 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);
6161                                 if (useviewfbo)
6162                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6163                         }
6164                 }
6165         }
6166
6167         // bloom texture is a different resolution
6168         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6169         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6170         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6171         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6172         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6173
6174         // set up a texcoord array for the full resolution screen image
6175         // (we have to keep this around to copy back during final render)
6176         r_fb.screentexcoord2f[0] = 0;
6177         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6178         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6179         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6180         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6181         r_fb.screentexcoord2f[5] = 0;
6182         r_fb.screentexcoord2f[6] = 0;
6183         r_fb.screentexcoord2f[7] = 0;
6184
6185         if(r_fb.fbo) 
6186         {
6187                 for (i = 1;i < 8;i += 2)
6188                 {
6189                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6190                 }
6191         }
6192
6193         // set up a texcoord array for the reduced resolution bloom image
6194         // (which will be additive blended over the screen image)
6195         r_fb.bloomtexcoord2f[0] = 0;
6196         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6197         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6198         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6199         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6200         r_fb.bloomtexcoord2f[5] = 0;
6201         r_fb.bloomtexcoord2f[6] = 0;
6202         r_fb.bloomtexcoord2f[7] = 0;
6203
6204         switch(vid.renderpath)
6205         {
6206         case RENDERPATH_GL11:
6207         case RENDERPATH_GL13:
6208         case RENDERPATH_GL20:
6209         case RENDERPATH_SOFT:
6210         case RENDERPATH_GLES1:
6211         case RENDERPATH_GLES2:
6212                 break;
6213         case RENDERPATH_D3D9:
6214         case RENDERPATH_D3D10:
6215         case RENDERPATH_D3D11:
6216                 for (i = 0;i < 4;i++)
6217                 {
6218                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6219                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6220                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6221                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6222                 }
6223                 break;
6224         }
6225
6226         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6227
6228         if (r_fb.fbo)
6229                 r_refdef.view.clear = true;
6230 }
6231
6232 static void R_Bloom_MakeTexture(void)
6233 {
6234         int x, range, dir;
6235         float xoffset, yoffset, r, brighten;
6236         rtexture_t *intex;
6237         float colorscale = r_bloom_colorscale.value;
6238
6239         r_refdef.stats.bloom++;
6240     
6241 #if 0
6242     // this copy is unnecessary since it happens in R_BlendView already
6243         if (!r_fb.fbo)
6244         {
6245                 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);
6246                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6247         }
6248 #endif
6249
6250         // scale down screen texture to the bloom texture size
6251         CHECKGLERROR
6252         r_fb.bloomindex = 0;
6253         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6254         R_SetViewport(&r_fb.bloomviewport);
6255         GL_DepthTest(false);
6256         GL_BlendFunc(GL_ONE, GL_ZERO);
6257         GL_Color(colorscale, colorscale, colorscale, 1);
6258         // 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...
6259         switch(vid.renderpath)
6260         {
6261         case RENDERPATH_GL11:
6262         case RENDERPATH_GL13:
6263         case RENDERPATH_GL20:
6264         case RENDERPATH_GLES1:
6265         case RENDERPATH_GLES2:
6266         case RENDERPATH_SOFT:
6267                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6268                 break;
6269         case RENDERPATH_D3D9:
6270         case RENDERPATH_D3D10:
6271         case RENDERPATH_D3D11:
6272                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6273                 break;
6274         }
6275         // TODO: do boxfilter scale-down in shader?
6276         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6277         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6279
6280         // we now have a properly scaled bloom image
6281         if (!r_fb.bloomfbo[r_fb.bloomindex])
6282         {
6283                 // copy it into the bloom texture
6284                 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);
6285                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6286         }
6287
6288         // multiply bloom image by itself as many times as desired
6289         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6290         {
6291                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6292                 r_fb.bloomindex ^= 1;
6293                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6294                 x *= 2;
6295                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6296                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6297                 {
6298                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6299                         GL_Color(r,r,r,1); // apply fix factor
6300                 }
6301                 else
6302                 {
6303                         if(x <= 2)
6304                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6305                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6306                         GL_Color(1,1,1,1); // no fix factor supported here
6307                 }
6308                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6309                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6310                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6311                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6312
6313                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6314                 {
6315                         // copy the darkened image to a texture
6316                         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);
6317                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6318                 }
6319         }
6320
6321         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6322         brighten = r_bloom_brighten.value;
6323         brighten = sqrt(brighten);
6324         if(range >= 1)
6325                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6326
6327         for (dir = 0;dir < 2;dir++)
6328         {
6329                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6330                 r_fb.bloomindex ^= 1;
6331                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6332                 // blend on at multiple vertical offsets to achieve a vertical blur
6333                 // TODO: do offset blends using GLSL
6334                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6335                 GL_BlendFunc(GL_ONE, GL_ZERO);
6336                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6337                 for (x = -range;x <= range;x++)
6338                 {
6339                         if (!dir){xoffset = 0;yoffset = x;}
6340                         else {xoffset = x;yoffset = 0;}
6341                         xoffset /= (float)r_fb.bloomtexturewidth;
6342                         yoffset /= (float)r_fb.bloomtextureheight;
6343                         // compute a texcoord array with the specified x and y offset
6344                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6345                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6346                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6347                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6348                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6349                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6350                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6351                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6352                         // this r value looks like a 'dot' particle, fading sharply to
6353                         // black at the edges
6354                         // (probably not realistic but looks good enough)
6355                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6356                         //r = brighten/(range*2+1);
6357                         r = brighten / (range * 2 + 1);
6358                         if(range >= 1)
6359                                 r *= (1 - x*x/(float)(range*range));
6360                         GL_Color(r, r, r, 1);
6361                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6362                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6363                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6364                         GL_BlendFunc(GL_ONE, GL_ONE);
6365                 }
6366
6367                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6368                 {
6369                         // copy the vertically or horizontally blurred bloom view to a texture
6370                         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);
6371                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6372                 }
6373         }
6374 }
6375
6376 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6377 {
6378         unsigned int permutation;
6379         float uservecs[4][4];
6380
6381         R_EntityMatrix(&identitymatrix);
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         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6914                 // in sRGB fallback, behave similar to true sRGB: convert this
6915                 // value from linear to sRGB
6916                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6917
6918         R_RenderView_UpdateViewVectors();
6919
6920         R_Shadow_UpdateWorldLightSelection();
6921
6922         R_Bloom_StartFrame();
6923
6924         // apply bloom brightness offset
6925         if(r_fb.bloomtexture[0])
6926                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6927
6928         R_Water_StartFrame();
6929
6930         // now we probably have an fbo to render into
6931         fbo = r_fb.fbo;
6932         depthtexture = r_fb.depthtexture;
6933         colortexture = r_fb.colortexture;
6934
6935         CHECKGLERROR
6936         if (r_timereport_active)
6937                 R_TimeReport("viewsetup");
6938
6939         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6940
6941         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6942         {
6943                 R_ClearScreen(r_refdef.fogenabled);
6944                 if (r_timereport_active)
6945                         R_TimeReport("viewclear");
6946         }
6947         r_refdef.view.clear = true;
6948
6949         r_refdef.view.showdebug = true;
6950
6951         R_View_Update();
6952         if (r_timereport_active)
6953                 R_TimeReport("visibility");
6954
6955         R_AnimCache_CacheVisibleEntities();
6956         if (r_timereport_active)
6957                 R_TimeReport("animcache");
6958
6959         R_Shadow_UpdateBounceGridTexture();
6960         if (r_timereport_active && r_shadow_bouncegrid.integer)
6961                 R_TimeReport("bouncegrid");
6962
6963         r_fb.water.numwaterplanes = 0;
6964         if (r_fb.water.enabled)
6965                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6966
6967         R_RenderScene(fbo, depthtexture, colortexture);
6968         r_fb.water.numwaterplanes = 0;
6969
6970         R_BlendView(fbo, depthtexture, colortexture);
6971         if (r_timereport_active)
6972                 R_TimeReport("blendview");
6973
6974         GL_Scissor(0, 0, vid.width, vid.height);
6975         GL_ScissorTest(false);
6976
6977         r_refdef.view.matrix = originalmatrix;
6978
6979         CHECKGLERROR
6980 }
6981
6982 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6983 {
6984         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6985         {
6986                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6987                 if (r_timereport_active)
6988                         R_TimeReport("waterworld");
6989         }
6990
6991         // don't let sound skip if going slow
6992         if (r_refdef.scene.extraupdate)
6993                 S_ExtraUpdate ();
6994
6995         R_DrawModelsAddWaterPlanes();
6996         if (r_timereport_active)
6997                 R_TimeReport("watermodels");
6998
6999         if (r_fb.water.numwaterplanes)
7000         {
7001                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7002                 if (r_timereport_active)
7003                         R_TimeReport("waterscenes");
7004         }
7005 }
7006
7007 extern cvar_t cl_locs_show;
7008 static void R_DrawLocs(void);
7009 static void R_DrawEntityBBoxes(void);
7010 static void R_DrawModelDecals(void);
7011 extern cvar_t cl_decals_newsystem;
7012 extern qboolean r_shadow_usingdeferredprepass;
7013 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7014 {
7015         qboolean shadowmapping = false;
7016
7017         if (r_timereport_active)
7018                 R_TimeReport("beginscene");
7019
7020         r_refdef.stats.renders++;
7021
7022         R_UpdateFog();
7023
7024         // don't let sound skip if going slow
7025         if (r_refdef.scene.extraupdate)
7026                 S_ExtraUpdate ();
7027
7028         R_MeshQueue_BeginScene();
7029
7030         R_SkyStartFrame();
7031
7032         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);
7033
7034         if (r_timereport_active)
7035                 R_TimeReport("skystartframe");
7036
7037         if (cl.csqc_vidvars.drawworld)
7038         {
7039                 // don't let sound skip if going slow
7040                 if (r_refdef.scene.extraupdate)
7041                         S_ExtraUpdate ();
7042
7043                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7044                 {
7045                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7046                         if (r_timereport_active)
7047                                 R_TimeReport("worldsky");
7048                 }
7049
7050                 if (R_DrawBrushModelsSky() && r_timereport_active)
7051                         R_TimeReport("bmodelsky");
7052
7053                 if (skyrendermasked && skyrenderlater)
7054                 {
7055                         // we have to force off the water clipping plane while rendering sky
7056                         R_SetupView(false, fbo, depthtexture, colortexture);
7057                         R_Sky();
7058                         R_SetupView(true, fbo, depthtexture, colortexture);
7059                         if (r_timereport_active)
7060                                 R_TimeReport("sky");
7061                 }
7062         }
7063
7064         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7065         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7066                 R_Shadow_PrepareModelShadows();
7067         if (r_timereport_active)
7068                 R_TimeReport("preparelights");
7069
7070         if (R_Shadow_ShadowMappingEnabled())
7071                 shadowmapping = true;
7072
7073         if (r_shadow_usingdeferredprepass)
7074                 R_Shadow_DrawPrepass();
7075
7076         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7077         {
7078                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7079                 if (r_timereport_active)
7080                         R_TimeReport("worlddepth");
7081         }
7082         if (r_depthfirst.integer >= 2)
7083         {
7084                 R_DrawModelsDepth();
7085                 if (r_timereport_active)
7086                         R_TimeReport("modeldepth");
7087         }
7088
7089         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7090         {
7091                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7092                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7093                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7094                 // don't let sound skip if going slow
7095                 if (r_refdef.scene.extraupdate)
7096                         S_ExtraUpdate ();
7097         }
7098
7099         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7100         {
7101                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7102                 if (r_timereport_active)
7103                         R_TimeReport("world");
7104         }
7105
7106         // don't let sound skip if going slow
7107         if (r_refdef.scene.extraupdate)
7108                 S_ExtraUpdate ();
7109
7110         R_DrawModels();
7111         if (r_timereport_active)
7112                 R_TimeReport("models");
7113
7114         // don't let sound skip if going slow
7115         if (r_refdef.scene.extraupdate)
7116                 S_ExtraUpdate ();
7117
7118         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7119         {
7120                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7121                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7122                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7123                 // don't let sound skip if going slow
7124                 if (r_refdef.scene.extraupdate)
7125                         S_ExtraUpdate ();
7126         }
7127
7128         if (!r_shadow_usingdeferredprepass)
7129         {
7130                 R_Shadow_DrawLights();
7131                 if (r_timereport_active)
7132                         R_TimeReport("rtlights");
7133         }
7134
7135         // don't let sound skip if going slow
7136         if (r_refdef.scene.extraupdate)
7137                 S_ExtraUpdate ();
7138
7139         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7140         {
7141                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7142                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7143                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7144                 // don't let sound skip if going slow
7145                 if (r_refdef.scene.extraupdate)
7146                         S_ExtraUpdate ();
7147         }
7148
7149         if (cl.csqc_vidvars.drawworld)
7150         {
7151                 if (cl_decals_newsystem.integer)
7152                 {
7153                         R_DrawModelDecals();
7154                         if (r_timereport_active)
7155                                 R_TimeReport("modeldecals");
7156                 }
7157                 else
7158                 {
7159                         R_DrawDecals();
7160                         if (r_timereport_active)
7161                                 R_TimeReport("decals");
7162                 }
7163
7164                 R_DrawParticles();
7165                 if (r_timereport_active)
7166                         R_TimeReport("particles");
7167
7168                 R_DrawExplosions();
7169                 if (r_timereport_active)
7170                         R_TimeReport("explosions");
7171
7172                 R_DrawLightningBeams();
7173                 if (r_timereport_active)
7174                         R_TimeReport("lightning");
7175         }
7176
7177         if (cl.csqc_loaded)
7178                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7179
7180         if (r_refdef.view.showdebug)
7181         {
7182                 if (cl_locs_show.integer)
7183                 {
7184                         R_DrawLocs();
7185                         if (r_timereport_active)
7186                                 R_TimeReport("showlocs");
7187                 }
7188
7189                 if (r_drawportals.integer)
7190                 {
7191                         R_DrawPortals();
7192                         if (r_timereport_active)
7193                                 R_TimeReport("portals");
7194                 }
7195
7196                 if (r_showbboxes.value > 0)
7197                 {
7198                         R_DrawEntityBBoxes();
7199                         if (r_timereport_active)
7200                                 R_TimeReport("bboxes");
7201                 }
7202         }
7203
7204         if (r_transparent.integer)
7205         {
7206                 R_MeshQueue_RenderTransparent();
7207                 if (r_timereport_active)
7208                         R_TimeReport("drawtrans");
7209         }
7210
7211         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))
7212         {
7213                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7214                 if (r_timereport_active)
7215                         R_TimeReport("worlddebug");
7216                 R_DrawModelsDebug();
7217                 if (r_timereport_active)
7218                         R_TimeReport("modeldebug");
7219         }
7220
7221         if (cl.csqc_vidvars.drawworld)
7222         {
7223                 R_Shadow_DrawCoronas();
7224                 if (r_timereport_active)
7225                         R_TimeReport("coronas");
7226         }
7227
7228 #if 0
7229         {
7230                 GL_DepthTest(false);
7231                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7232                 GL_Color(1, 1, 1, 1);
7233                 qglBegin(GL_POLYGON);
7234                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7235                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7236                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7237                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7238                 qglEnd();
7239                 qglBegin(GL_POLYGON);
7240                 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]);
7241                 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]);
7242                 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]);
7243                 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]);
7244                 qglEnd();
7245                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7246         }
7247 #endif
7248
7249         // don't let sound skip if going slow
7250         if (r_refdef.scene.extraupdate)
7251                 S_ExtraUpdate ();
7252 }
7253
7254 static const unsigned short bboxelements[36] =
7255 {
7256         5, 1, 3, 5, 3, 7,
7257         6, 2, 0, 6, 0, 4,
7258         7, 3, 2, 7, 2, 6,
7259         4, 0, 1, 4, 1, 5,
7260         4, 5, 7, 4, 7, 6,
7261         1, 0, 2, 1, 2, 3,
7262 };
7263
7264 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7265 {
7266         int i;
7267         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7268
7269         RSurf_ActiveWorldEntity();
7270
7271         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7272         GL_DepthMask(false);
7273         GL_DepthRange(0, 1);
7274         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7275 //      R_Mesh_ResetTextureState();
7276
7277         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7278         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7279         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7280         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7281         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7282         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7283         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7284         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7285         R_FillColors(color4f, 8, cr, cg, cb, ca);
7286         if (r_refdef.fogenabled)
7287         {
7288                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7289                 {
7290                         f1 = RSurf_FogVertex(v);
7291                         f2 = 1 - f1;
7292                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7293                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7294                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7295                 }
7296         }
7297         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7298         R_Mesh_ResetTextureState();
7299         R_SetupShader_Generic_NoTexture(false, false);
7300         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7301 }
7302
7303 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7304 {
7305         prvm_prog_t *prog = SVVM_prog;
7306         int i;
7307         float color[4];
7308         prvm_edict_t *edict;
7309
7310         // this function draws bounding boxes of server entities
7311         if (!sv.active)
7312                 return;
7313
7314         GL_CullFace(GL_NONE);
7315         R_SetupShader_Generic_NoTexture(false, false);
7316
7317         for (i = 0;i < numsurfaces;i++)
7318         {
7319                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7320                 switch ((int)PRVM_serveredictfloat(edict, solid))
7321                 {
7322                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7323                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7324                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7325                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7326                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7327                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7328                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7329                 }
7330                 color[3] *= r_showbboxes.value;
7331                 color[3] = bound(0, color[3], 1);
7332                 GL_DepthTest(!r_showdisabledepthtest.integer);
7333                 GL_CullFace(r_refdef.view.cullface_front);
7334                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7335         }
7336 }
7337
7338 static void R_DrawEntityBBoxes(void)
7339 {
7340         int i;
7341         prvm_edict_t *edict;
7342         vec3_t center;
7343         prvm_prog_t *prog = SVVM_prog;
7344
7345         // this function draws bounding boxes of server entities
7346         if (!sv.active)
7347                 return;
7348
7349         for (i = 0;i < prog->num_edicts;i++)
7350         {
7351                 edict = PRVM_EDICT_NUM(i);
7352                 if (edict->priv.server->free)
7353                         continue;
7354                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7355                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7356                         continue;
7357                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7358                         continue;
7359                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7360                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7361         }
7362 }
7363
7364 static const int nomodelelement3i[24] =
7365 {
7366         5, 2, 0,
7367         5, 1, 2,
7368         5, 0, 3,
7369         5, 3, 1,
7370         0, 2, 4,
7371         2, 1, 4,
7372         3, 0, 4,
7373         1, 3, 4
7374 };
7375
7376 static const unsigned short nomodelelement3s[24] =
7377 {
7378         5, 2, 0,
7379         5, 1, 2,
7380         5, 0, 3,
7381         5, 3, 1,
7382         0, 2, 4,
7383         2, 1, 4,
7384         3, 0, 4,
7385         1, 3, 4
7386 };
7387
7388 static const float nomodelvertex3f[6*3] =
7389 {
7390         -16,   0,   0,
7391          16,   0,   0,
7392           0, -16,   0,
7393           0,  16,   0,
7394           0,   0, -16,
7395           0,   0,  16
7396 };
7397
7398 static const float nomodelcolor4f[6*4] =
7399 {
7400         0.0f, 0.0f, 0.5f, 1.0f,
7401         0.0f, 0.0f, 0.5f, 1.0f,
7402         0.0f, 0.5f, 0.0f, 1.0f,
7403         0.0f, 0.5f, 0.0f, 1.0f,
7404         0.5f, 0.0f, 0.0f, 1.0f,
7405         0.5f, 0.0f, 0.0f, 1.0f
7406 };
7407
7408 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7409 {
7410         int i;
7411         float f1, f2, *c;
7412         float color4f[6*4];
7413
7414         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);
7415
7416         // this is only called once per entity so numsurfaces is always 1, and
7417         // surfacelist is always {0}, so this code does not handle batches
7418
7419         if (rsurface.ent_flags & RENDER_ADDITIVE)
7420         {
7421                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7422                 GL_DepthMask(false);
7423         }
7424         else if (rsurface.colormod[3] < 1)
7425         {
7426                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7427                 GL_DepthMask(false);
7428         }
7429         else
7430         {
7431                 GL_BlendFunc(GL_ONE, GL_ZERO);
7432                 GL_DepthMask(true);
7433         }
7434         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7435         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7436         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7437         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7438         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7439         for (i = 0, c = color4f;i < 6;i++, c += 4)
7440         {
7441                 c[0] *= rsurface.colormod[0];
7442                 c[1] *= rsurface.colormod[1];
7443                 c[2] *= rsurface.colormod[2];
7444                 c[3] *= rsurface.colormod[3];
7445         }
7446         if (r_refdef.fogenabled)
7447         {
7448                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7449                 {
7450                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7451                         f2 = 1 - f1;
7452                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7453                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7454                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7455                 }
7456         }
7457 //      R_Mesh_ResetTextureState();
7458         R_SetupShader_Generic_NoTexture(false, false);
7459         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7460         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7461 }
7462
7463 void R_DrawNoModel(entity_render_t *ent)
7464 {
7465         vec3_t org;
7466         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7467         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7468                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7469         else
7470                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7471 }
7472
7473 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7474 {
7475         vec3_t right1, right2, diff, normal;
7476
7477         VectorSubtract (org2, org1, normal);
7478
7479         // calculate 'right' vector for start
7480         VectorSubtract (r_refdef.view.origin, org1, diff);
7481         CrossProduct (normal, diff, right1);
7482         VectorNormalize (right1);
7483
7484         // calculate 'right' vector for end
7485         VectorSubtract (r_refdef.view.origin, org2, diff);
7486         CrossProduct (normal, diff, right2);
7487         VectorNormalize (right2);
7488
7489         vert[ 0] = org1[0] + width * right1[0];
7490         vert[ 1] = org1[1] + width * right1[1];
7491         vert[ 2] = org1[2] + width * right1[2];
7492         vert[ 3] = org1[0] - width * right1[0];
7493         vert[ 4] = org1[1] - width * right1[1];
7494         vert[ 5] = org1[2] - width * right1[2];
7495         vert[ 6] = org2[0] - width * right2[0];
7496         vert[ 7] = org2[1] - width * right2[1];
7497         vert[ 8] = org2[2] - width * right2[2];
7498         vert[ 9] = org2[0] + width * right2[0];
7499         vert[10] = org2[1] + width * right2[1];
7500         vert[11] = org2[2] + width * right2[2];
7501 }
7502
7503 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)
7504 {
7505         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7506         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7507         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7508         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7509         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7510         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7511         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7512         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7513         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7514         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7515         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7516         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7517 }
7518
7519 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7520 {
7521         int i;
7522         float *vertex3f;
7523         float v[3];
7524         VectorSet(v, x, y, z);
7525         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7526                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7527                         break;
7528         if (i == mesh->numvertices)
7529         {
7530                 if (mesh->numvertices < mesh->maxvertices)
7531                 {
7532                         VectorCopy(v, vertex3f);
7533                         mesh->numvertices++;
7534                 }
7535                 return mesh->numvertices;
7536         }
7537         else
7538                 return i;
7539 }
7540
7541 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7542 {
7543         int i;
7544         int *e, element[3];
7545         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7546         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7547         e = mesh->element3i + mesh->numtriangles * 3;
7548         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7549         {
7550                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7551                 if (mesh->numtriangles < mesh->maxtriangles)
7552                 {
7553                         *e++ = element[0];
7554                         *e++ = element[1];
7555                         *e++ = element[2];
7556                         mesh->numtriangles++;
7557                 }
7558                 element[1] = element[2];
7559         }
7560 }
7561
7562 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7563 {
7564         int i;
7565         int *e, element[3];
7566         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7567         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7568         e = mesh->element3i + mesh->numtriangles * 3;
7569         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7570         {
7571                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7572                 if (mesh->numtriangles < mesh->maxtriangles)
7573                 {
7574                         *e++ = element[0];
7575                         *e++ = element[1];
7576                         *e++ = element[2];
7577                         mesh->numtriangles++;
7578                 }
7579                 element[1] = element[2];
7580         }
7581 }
7582
7583 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7584 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7585 {
7586         int planenum, planenum2;
7587         int w;
7588         int tempnumpoints;
7589         mplane_t *plane, *plane2;
7590         double maxdist;
7591         double temppoints[2][256*3];
7592         // figure out how large a bounding box we need to properly compute this brush
7593         maxdist = 0;
7594         for (w = 0;w < numplanes;w++)
7595                 maxdist = max(maxdist, fabs(planes[w].dist));
7596         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7597         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7598         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7599         {
7600                 w = 0;
7601                 tempnumpoints = 4;
7602                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7603                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7604                 {
7605                         if (planenum2 == planenum)
7606                                 continue;
7607                         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);
7608                         w = !w;
7609                 }
7610                 if (tempnumpoints < 3)
7611                         continue;
7612                 // generate elements forming a triangle fan for this polygon
7613                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7614         }
7615 }
7616
7617 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)
7618 {
7619         texturelayer_t *layer;
7620         layer = t->currentlayers + t->currentnumlayers++;
7621         layer->type = type;
7622         layer->depthmask = depthmask;
7623         layer->blendfunc1 = blendfunc1;
7624         layer->blendfunc2 = blendfunc2;
7625         layer->texture = texture;
7626         layer->texmatrix = *matrix;
7627         layer->color[0] = r;
7628         layer->color[1] = g;
7629         layer->color[2] = b;
7630         layer->color[3] = a;
7631 }
7632
7633 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7634 {
7635         if(parms[0] == 0 && parms[1] == 0)
7636                 return false;
7637         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7638                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7639                         return false;
7640         return true;
7641 }
7642
7643 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7644 {
7645         double index, f;
7646         index = parms[2] + rsurface.shadertime * parms[3];
7647         index -= floor(index);
7648         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7649         {
7650         default:
7651         case Q3WAVEFUNC_NONE:
7652         case Q3WAVEFUNC_NOISE:
7653         case Q3WAVEFUNC_COUNT:
7654                 f = 0;
7655                 break;
7656         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7657         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7658         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7659         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7660         case Q3WAVEFUNC_TRIANGLE:
7661                 index *= 4;
7662                 f = index - floor(index);
7663                 if (index < 1)
7664                 {
7665                         // f = f;
7666                 }
7667                 else if (index < 2)
7668                         f = 1 - f;
7669                 else if (index < 3)
7670                         f = -f;
7671                 else
7672                         f = -(1 - f);
7673                 break;
7674         }
7675         f = parms[0] + parms[1] * f;
7676         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7677                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7678         return (float) f;
7679 }
7680
7681 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7682 {
7683         int w, h, idx;
7684         double f;
7685         double offsetd[2];
7686         float tcmat[12];
7687         matrix4x4_t matrix, temp;
7688         switch(tcmod->tcmod)
7689         {
7690                 case Q3TCMOD_COUNT:
7691                 case Q3TCMOD_NONE:
7692                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7693                                 matrix = r_waterscrollmatrix;
7694                         else
7695                                 matrix = identitymatrix;
7696                         break;
7697                 case Q3TCMOD_ENTITYTRANSLATE:
7698                         // this is used in Q3 to allow the gamecode to control texcoord
7699                         // scrolling on the entity, which is not supported in darkplaces yet.
7700                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7701                         break;
7702                 case Q3TCMOD_ROTATE:
7703                         f = tcmod->parms[0] * rsurface.shadertime;
7704                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7705                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7706                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7707                         break;
7708                 case Q3TCMOD_SCALE:
7709                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7710                         break;
7711                 case Q3TCMOD_SCROLL:
7712                         // extra care is needed because of precision breakdown with large values of time
7713                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7714                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7715                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7716                         break;
7717                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7718                         w = (int) tcmod->parms[0];
7719                         h = (int) tcmod->parms[1];
7720                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7721                         f = f - floor(f);
7722                         idx = (int) floor(f * w * h);
7723                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7724                         break;
7725                 case Q3TCMOD_STRETCH:
7726                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7727                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7728                         break;
7729                 case Q3TCMOD_TRANSFORM:
7730                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7731                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7732                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7733                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7734                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7735                         break;
7736                 case Q3TCMOD_TURBULENT:
7737                         // this is handled in the RSurf_PrepareVertices function
7738                         matrix = identitymatrix;
7739                         break;
7740         }
7741         temp = *texmatrix;
7742         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7743 }
7744
7745 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7746 {
7747         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7748         char name[MAX_QPATH];
7749         skinframe_t *skinframe;
7750         unsigned char pixels[296*194];
7751         strlcpy(cache->name, skinname, sizeof(cache->name));
7752         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7753         if (developer_loading.integer)
7754                 Con_Printf("loading %s\n", name);
7755         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7756         if (!skinframe || !skinframe->base)
7757         {
7758                 unsigned char *f;
7759                 fs_offset_t filesize;
7760                 skinframe = NULL;
7761                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7762                 if (f)
7763                 {
7764                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7765                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7766                         Mem_Free(f);
7767                 }
7768         }
7769         cache->skinframe = skinframe;
7770 }
7771
7772 texture_t *R_GetCurrentTexture(texture_t *t)
7773 {
7774         int i;
7775         const entity_render_t *ent = rsurface.entity;
7776         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7777         q3shaderinfo_layer_tcmod_t *tcmod;
7778
7779         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7780                 return t->currentframe;
7781         t->update_lastrenderframe = r_textureframe;
7782         t->update_lastrenderentity = (void *)ent;
7783
7784         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7785                 t->camera_entity = ent->entitynumber;
7786         else
7787                 t->camera_entity = 0;
7788
7789         // switch to an alternate material if this is a q1bsp animated material
7790         {
7791                 texture_t *texture = t;
7792                 int s = rsurface.ent_skinnum;
7793                 if ((unsigned int)s >= (unsigned int)model->numskins)
7794                         s = 0;
7795                 if (model->skinscenes)
7796                 {
7797                         if (model->skinscenes[s].framecount > 1)
7798                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7799                         else
7800                                 s = model->skinscenes[s].firstframe;
7801                 }
7802                 if (s > 0)
7803                         t = t + s * model->num_surfaces;
7804                 if (t->animated)
7805                 {
7806                         // use an alternate animation if the entity's frame is not 0,
7807                         // and only if the texture has an alternate animation
7808                         if (rsurface.ent_alttextures && t->anim_total[1])
7809                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7810                         else
7811                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7812                 }
7813                 texture->currentframe = t;
7814         }
7815
7816         // update currentskinframe to be a qw skin or animation frame
7817         if (rsurface.ent_qwskin >= 0)
7818         {
7819                 i = rsurface.ent_qwskin;
7820                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7821                 {
7822                         r_qwskincache_size = cl.maxclients;
7823                         if (r_qwskincache)
7824                                 Mem_Free(r_qwskincache);
7825                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7826                 }
7827                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7828                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7829                 t->currentskinframe = r_qwskincache[i].skinframe;
7830                 if (t->currentskinframe == NULL)
7831                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7832         }
7833         else if (t->numskinframes >= 2)
7834                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7835         if (t->backgroundnumskinframes >= 2)
7836                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7837
7838         t->currentmaterialflags = t->basematerialflags;
7839         t->currentalpha = rsurface.colormod[3];
7840         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7841                 t->currentalpha *= r_wateralpha.value;
7842         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7843                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7844         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7845                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7846         if (!(rsurface.ent_flags & RENDER_LIGHT))
7847                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7848         else if (FAKELIGHT_ENABLED)
7849         {
7850                 // no modellight if using fakelight for the map
7851         }
7852         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7853         {
7854                 // pick a model lighting mode
7855                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7856                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7857                 else
7858                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7859         }
7860         if (rsurface.ent_flags & RENDER_ADDITIVE)
7861                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7862         else if (t->currentalpha < 1)
7863                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7864         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7865         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7866                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7867         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7868                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7869         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7870                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7871         if (t->backgroundnumskinframes)
7872                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7873         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7874         {
7875                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7876                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7877         }
7878         else
7879                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7880         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7881         {
7882                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7883                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7884         }
7885         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7886                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7887
7888         // there is no tcmod
7889         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7890         {
7891                 t->currenttexmatrix = r_waterscrollmatrix;
7892                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7893         }
7894         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7895         {
7896                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7897                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7898         }
7899
7900         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7901                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7902         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7903                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7904
7905         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7906         if (t->currentskinframe->qpixels)
7907                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7908         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7909         if (!t->basetexture)
7910                 t->basetexture = r_texture_notexture;
7911         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7912         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7913         t->nmaptexture = t->currentskinframe->nmap;
7914         if (!t->nmaptexture)
7915                 t->nmaptexture = r_texture_blanknormalmap;
7916         t->glosstexture = r_texture_black;
7917         t->glowtexture = t->currentskinframe->glow;
7918         t->fogtexture = t->currentskinframe->fog;
7919         t->reflectmasktexture = t->currentskinframe->reflect;
7920         if (t->backgroundnumskinframes)
7921         {
7922                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7923                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7924                 t->backgroundglosstexture = r_texture_black;
7925                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7926                 if (!t->backgroundnmaptexture)
7927                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7928                 // make sure that if glow is going to be used, both textures are not NULL
7929                 if (!t->backgroundglowtexture && t->glowtexture)
7930                         t->backgroundglowtexture = r_texture_black;
7931                 if (!t->glowtexture && t->backgroundglowtexture)
7932                         t->glowtexture = r_texture_black;
7933         }
7934         else
7935         {
7936                 t->backgroundbasetexture = r_texture_white;
7937                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7938                 t->backgroundglosstexture = r_texture_black;
7939                 t->backgroundglowtexture = NULL;
7940         }
7941         t->specularpower = r_shadow_glossexponent.value;
7942         // TODO: store reference values for these in the texture?
7943         t->specularscale = 0;
7944         if (r_shadow_gloss.integer > 0)
7945         {
7946                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7947                 {
7948                         if (r_shadow_glossintensity.value > 0)
7949                         {
7950                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7951                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7952                                 t->specularscale = r_shadow_glossintensity.value;
7953                         }
7954                 }
7955                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7956                 {
7957                         t->glosstexture = r_texture_white;
7958                         t->backgroundglosstexture = r_texture_white;
7959                         t->specularscale = r_shadow_gloss2intensity.value;
7960                         t->specularpower = r_shadow_gloss2exponent.value;
7961                 }
7962         }
7963         t->specularscale *= t->specularscalemod;
7964         t->specularpower *= t->specularpowermod;
7965         t->rtlightambient = 0;
7966
7967         // lightmaps mode looks bad with dlights using actual texturing, so turn
7968         // off the colormap and glossmap, but leave the normalmap on as it still
7969         // accurately represents the shading involved
7970         if (gl_lightmaps.integer)
7971         {
7972                 t->basetexture = r_texture_grey128;
7973                 t->pantstexture = r_texture_black;
7974                 t->shirttexture = r_texture_black;
7975                 if (gl_lightmaps.integer < 2)
7976                         t->nmaptexture = r_texture_blanknormalmap;
7977                 t->glosstexture = r_texture_black;
7978                 t->glowtexture = NULL;
7979                 t->fogtexture = NULL;
7980                 t->reflectmasktexture = NULL;
7981                 t->backgroundbasetexture = NULL;
7982                 if (gl_lightmaps.integer < 2)
7983                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7984                 t->backgroundglosstexture = r_texture_black;
7985                 t->backgroundglowtexture = NULL;
7986                 t->specularscale = 0;
7987                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7988         }
7989
7990         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7991         VectorClear(t->dlightcolor);
7992         t->currentnumlayers = 0;
7993         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7994         {
7995                 int blendfunc1, blendfunc2;
7996                 qboolean depthmask;
7997                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7998                 {
7999                         blendfunc1 = GL_SRC_ALPHA;
8000                         blendfunc2 = GL_ONE;
8001                 }
8002                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8003                 {
8004                         blendfunc1 = GL_SRC_ALPHA;
8005                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8006                 }
8007                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8008                 {
8009                         blendfunc1 = t->customblendfunc[0];
8010                         blendfunc2 = t->customblendfunc[1];
8011                 }
8012                 else
8013                 {
8014                         blendfunc1 = GL_ONE;
8015                         blendfunc2 = GL_ZERO;
8016                 }
8017                 // don't colormod evilblend textures
8018                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8019                         VectorSet(t->lightmapcolor, 1, 1, 1);
8020                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8021                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8022                 {
8023                         // fullbright is not affected by r_refdef.lightmapintensity
8024                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8025                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8026                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8027                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8028                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8029                 }
8030                 else
8031                 {
8032                         vec3_t ambientcolor;
8033                         float colorscale;
8034                         // set the color tint used for lights affecting this surface
8035                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8036                         colorscale = 2;
8037                         // q3bsp has no lightmap updates, so the lightstylevalue that
8038                         // would normally be baked into the lightmap must be
8039                         // applied to the color
8040                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8041                         if (model->type == mod_brushq3)
8042                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8043                         colorscale *= r_refdef.lightmapintensity;
8044                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8045                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8046                         // basic lit geometry
8047                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8048                         // add pants/shirt if needed
8049                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8050                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8051                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8052                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8053                         // now add ambient passes if needed
8054                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8055                         {
8056                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8057                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8058                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8059                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8060                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8061                         }
8062                 }
8063                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8064                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8065                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8066                 {
8067                         // if this is opaque use alpha blend which will darken the earlier
8068                         // passes cheaply.
8069                         //
8070                         // if this is an alpha blended material, all the earlier passes
8071                         // were darkened by fog already, so we only need to add the fog
8072                         // color ontop through the fog mask texture
8073                         //
8074                         // if this is an additive blended material, all the earlier passes
8075                         // were darkened by fog already, and we should not add fog color
8076                         // (because the background was not darkened, there is no fog color
8077                         // that was lost behind it).
8078                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8079                 }
8080         }
8081
8082         return t->currentframe;
8083 }
8084
8085 rsurfacestate_t rsurface;
8086
8087 void RSurf_ActiveWorldEntity(void)
8088 {
8089         dp_model_t *model = r_refdef.scene.worldmodel;
8090         //if (rsurface.entity == r_refdef.scene.worldentity)
8091         //      return;
8092         rsurface.entity = r_refdef.scene.worldentity;
8093         rsurface.skeleton = NULL;
8094         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8095         rsurface.ent_skinnum = 0;
8096         rsurface.ent_qwskin = -1;
8097         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8098         rsurface.shadertime = r_refdef.scene.time;
8099         rsurface.matrix = identitymatrix;
8100         rsurface.inversematrix = identitymatrix;
8101         rsurface.matrixscale = 1;
8102         rsurface.inversematrixscale = 1;
8103         R_EntityMatrix(&identitymatrix);
8104         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8105         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8106         rsurface.fograngerecip = r_refdef.fograngerecip;
8107         rsurface.fogheightfade = r_refdef.fogheightfade;
8108         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8109         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8110         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8111         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8112         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8113         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8114         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8115         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8116         rsurface.colormod[3] = 1;
8117         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8118         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8119         rsurface.frameblend[0].lerp = 1;
8120         rsurface.ent_alttextures = false;
8121         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8122         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8123         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8124         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8126         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8127         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8129         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8130         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8131         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8132         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8133         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8134         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8135         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8136         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8137         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8138         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8139         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8141         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8142         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8143         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8144         rsurface.modelelement3i = model->surfmesh.data_element3i;
8145         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8146         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8147         rsurface.modelelement3s = model->surfmesh.data_element3s;
8148         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8149         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8150         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8151         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8152         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8153         rsurface.modelsurfaces = model->data_surfaces;
8154         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8155         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8156         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8157         rsurface.modelgeneratedvertex = false;
8158         rsurface.batchgeneratedvertex = false;
8159         rsurface.batchfirstvertex = 0;
8160         rsurface.batchnumvertices = 0;
8161         rsurface.batchfirsttriangle = 0;
8162         rsurface.batchnumtriangles = 0;
8163         rsurface.batchvertex3f  = NULL;
8164         rsurface.batchvertex3f_vertexbuffer = NULL;
8165         rsurface.batchvertex3f_bufferoffset = 0;
8166         rsurface.batchsvector3f = NULL;
8167         rsurface.batchsvector3f_vertexbuffer = NULL;
8168         rsurface.batchsvector3f_bufferoffset = 0;
8169         rsurface.batchtvector3f = NULL;
8170         rsurface.batchtvector3f_vertexbuffer = NULL;
8171         rsurface.batchtvector3f_bufferoffset = 0;
8172         rsurface.batchnormal3f  = NULL;
8173         rsurface.batchnormal3f_vertexbuffer = NULL;
8174         rsurface.batchnormal3f_bufferoffset = 0;
8175         rsurface.batchlightmapcolor4f = NULL;
8176         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8177         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8178         rsurface.batchtexcoordtexture2f = NULL;
8179         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8180         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8181         rsurface.batchtexcoordlightmap2f = NULL;
8182         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8183         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8184         rsurface.batchvertexmesh = NULL;
8185         rsurface.batchvertexmeshbuffer = NULL;
8186         rsurface.batchvertex3fbuffer = NULL;
8187         rsurface.batchelement3i = NULL;
8188         rsurface.batchelement3i_indexbuffer = NULL;
8189         rsurface.batchelement3i_bufferoffset = 0;
8190         rsurface.batchelement3s = NULL;
8191         rsurface.batchelement3s_indexbuffer = NULL;
8192         rsurface.batchelement3s_bufferoffset = 0;
8193         rsurface.passcolor4f = NULL;
8194         rsurface.passcolor4f_vertexbuffer = NULL;
8195         rsurface.passcolor4f_bufferoffset = 0;
8196         rsurface.forcecurrenttextureupdate = false;
8197 }
8198
8199 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8200 {
8201         dp_model_t *model = ent->model;
8202         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8203         //      return;
8204         rsurface.entity = (entity_render_t *)ent;
8205         rsurface.skeleton = ent->skeleton;
8206         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8207         rsurface.ent_skinnum = ent->skinnum;
8208         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
8209         rsurface.ent_flags = ent->flags;
8210         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8211         rsurface.matrix = ent->matrix;
8212         rsurface.inversematrix = ent->inversematrix;
8213         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8214         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8215         R_EntityMatrix(&rsurface.matrix);
8216         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8217         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8218         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8219         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8220         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8221         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8222         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8223         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8224         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8225         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8226         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8227         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8228         rsurface.colormod[3] = ent->alpha;
8229         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8230         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8231         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8232         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8233         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8234         if (ent->model->brush.submodel && !prepass)
8235         {
8236                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8237                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8238         }
8239         if (model->surfmesh.isanimated && model->AnimateVertices)
8240         {
8241                 if (ent->animcache_vertex3f)
8242                 {
8243                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8244                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8245                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8246                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8247                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8248                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8249                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8250                 }
8251                 else if (wanttangents)
8252                 {
8253                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8254                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8255                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8256                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8257                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8258                         rsurface.modelvertexmesh = NULL;
8259                         rsurface.modelvertexmeshbuffer = NULL;
8260                         rsurface.modelvertex3fbuffer = NULL;
8261                 }
8262                 else if (wantnormals)
8263                 {
8264                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8265                         rsurface.modelsvector3f = NULL;
8266                         rsurface.modeltvector3f = NULL;
8267                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8268                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8269                         rsurface.modelvertexmesh = NULL;
8270                         rsurface.modelvertexmeshbuffer = NULL;
8271                         rsurface.modelvertex3fbuffer = NULL;
8272                 }
8273                 else
8274                 {
8275                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8276                         rsurface.modelsvector3f = NULL;
8277                         rsurface.modeltvector3f = NULL;
8278                         rsurface.modelnormal3f = NULL;
8279                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8280                         rsurface.modelvertexmesh = NULL;
8281                         rsurface.modelvertexmeshbuffer = NULL;
8282                         rsurface.modelvertex3fbuffer = NULL;
8283                 }
8284                 rsurface.modelvertex3f_vertexbuffer = 0;
8285                 rsurface.modelvertex3f_bufferoffset = 0;
8286                 rsurface.modelsvector3f_vertexbuffer = 0;
8287                 rsurface.modelsvector3f_bufferoffset = 0;
8288                 rsurface.modeltvector3f_vertexbuffer = 0;
8289                 rsurface.modeltvector3f_bufferoffset = 0;
8290                 rsurface.modelnormal3f_vertexbuffer = 0;
8291                 rsurface.modelnormal3f_bufferoffset = 0;
8292                 rsurface.modelgeneratedvertex = true;
8293         }
8294         else
8295         {
8296                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8297                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8298                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8299                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8300                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8301                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8302                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8303                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8304                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8305                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8306                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8307                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8308                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8309                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8310                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8311                 rsurface.modelgeneratedvertex = false;
8312         }
8313         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8314         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8315         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8316         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8317         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8318         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8319         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8320         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8321         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8322         rsurface.modelelement3i = model->surfmesh.data_element3i;
8323         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8324         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8325         rsurface.modelelement3s = model->surfmesh.data_element3s;
8326         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8327         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8328         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8329         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8330         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8331         rsurface.modelsurfaces = model->data_surfaces;
8332         rsurface.batchgeneratedvertex = false;
8333         rsurface.batchfirstvertex = 0;
8334         rsurface.batchnumvertices = 0;
8335         rsurface.batchfirsttriangle = 0;
8336         rsurface.batchnumtriangles = 0;
8337         rsurface.batchvertex3f  = NULL;
8338         rsurface.batchvertex3f_vertexbuffer = NULL;
8339         rsurface.batchvertex3f_bufferoffset = 0;
8340         rsurface.batchsvector3f = NULL;
8341         rsurface.batchsvector3f_vertexbuffer = NULL;
8342         rsurface.batchsvector3f_bufferoffset = 0;
8343         rsurface.batchtvector3f = NULL;
8344         rsurface.batchtvector3f_vertexbuffer = NULL;
8345         rsurface.batchtvector3f_bufferoffset = 0;
8346         rsurface.batchnormal3f  = NULL;
8347         rsurface.batchnormal3f_vertexbuffer = NULL;
8348         rsurface.batchnormal3f_bufferoffset = 0;
8349         rsurface.batchlightmapcolor4f = NULL;
8350         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8351         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8352         rsurface.batchtexcoordtexture2f = NULL;
8353         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8354         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8355         rsurface.batchtexcoordlightmap2f = NULL;
8356         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8357         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8358         rsurface.batchvertexmesh = NULL;
8359         rsurface.batchvertexmeshbuffer = NULL;
8360         rsurface.batchvertex3fbuffer = NULL;
8361         rsurface.batchelement3i = NULL;
8362         rsurface.batchelement3i_indexbuffer = NULL;
8363         rsurface.batchelement3i_bufferoffset = 0;
8364         rsurface.batchelement3s = NULL;
8365         rsurface.batchelement3s_indexbuffer = NULL;
8366         rsurface.batchelement3s_bufferoffset = 0;
8367         rsurface.passcolor4f = NULL;
8368         rsurface.passcolor4f_vertexbuffer = NULL;
8369         rsurface.passcolor4f_bufferoffset = 0;
8370         rsurface.forcecurrenttextureupdate = false;
8371 }
8372
8373 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
8374 {
8375         rsurface.entity = r_refdef.scene.worldentity;
8376         rsurface.skeleton = NULL;
8377         rsurface.ent_skinnum = 0;
8378         rsurface.ent_qwskin = -1;
8379         rsurface.ent_flags = entflags;
8380         rsurface.shadertime = r_refdef.scene.time - shadertime;
8381         rsurface.modelnumvertices = numvertices;
8382         rsurface.modelnumtriangles = numtriangles;
8383         rsurface.matrix = *matrix;
8384         rsurface.inversematrix = *inversematrix;
8385         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8386         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8387         R_EntityMatrix(&rsurface.matrix);
8388         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8389         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8390         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8391         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8392         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8393         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8394         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8395         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8396         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8397         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8398         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8399         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8400         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8401         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8402         rsurface.frameblend[0].lerp = 1;
8403         rsurface.ent_alttextures = false;
8404         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8405         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8406         if (wanttangents)
8407         {
8408                 rsurface.modelvertex3f = (float *)vertex3f;
8409                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8410                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8411                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8412         }
8413         else if (wantnormals)
8414         {
8415                 rsurface.modelvertex3f = (float *)vertex3f;
8416                 rsurface.modelsvector3f = NULL;
8417                 rsurface.modeltvector3f = NULL;
8418                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8419         }
8420         else
8421         {
8422                 rsurface.modelvertex3f = (float *)vertex3f;
8423                 rsurface.modelsvector3f = NULL;
8424                 rsurface.modeltvector3f = NULL;
8425                 rsurface.modelnormal3f = NULL;
8426         }
8427         rsurface.modelvertexmesh = NULL;
8428         rsurface.modelvertexmeshbuffer = NULL;
8429         rsurface.modelvertex3fbuffer = NULL;
8430         rsurface.modelvertex3f_vertexbuffer = 0;
8431         rsurface.modelvertex3f_bufferoffset = 0;
8432         rsurface.modelsvector3f_vertexbuffer = 0;
8433         rsurface.modelsvector3f_bufferoffset = 0;
8434         rsurface.modeltvector3f_vertexbuffer = 0;
8435         rsurface.modeltvector3f_bufferoffset = 0;
8436         rsurface.modelnormal3f_vertexbuffer = 0;
8437         rsurface.modelnormal3f_bufferoffset = 0;
8438         rsurface.modelgeneratedvertex = true;
8439         rsurface.modellightmapcolor4f  = (float *)color4f;
8440         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8441         rsurface.modellightmapcolor4f_bufferoffset = 0;
8442         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8443         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8444         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8445         rsurface.modeltexcoordlightmap2f  = NULL;
8446         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8447         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8448         rsurface.modelelement3i = (int *)element3i;
8449         rsurface.modelelement3i_indexbuffer = NULL;
8450         rsurface.modelelement3i_bufferoffset = 0;
8451         rsurface.modelelement3s = (unsigned short *)element3s;
8452         rsurface.modelelement3s_indexbuffer = NULL;
8453         rsurface.modelelement3s_bufferoffset = 0;
8454         rsurface.modellightmapoffsets = NULL;
8455         rsurface.modelsurfaces = NULL;
8456         rsurface.batchgeneratedvertex = false;
8457         rsurface.batchfirstvertex = 0;
8458         rsurface.batchnumvertices = 0;
8459         rsurface.batchfirsttriangle = 0;
8460         rsurface.batchnumtriangles = 0;
8461         rsurface.batchvertex3f  = NULL;
8462         rsurface.batchvertex3f_vertexbuffer = NULL;
8463         rsurface.batchvertex3f_bufferoffset = 0;
8464         rsurface.batchsvector3f = NULL;
8465         rsurface.batchsvector3f_vertexbuffer = NULL;
8466         rsurface.batchsvector3f_bufferoffset = 0;
8467         rsurface.batchtvector3f = NULL;
8468         rsurface.batchtvector3f_vertexbuffer = NULL;
8469         rsurface.batchtvector3f_bufferoffset = 0;
8470         rsurface.batchnormal3f  = NULL;
8471         rsurface.batchnormal3f_vertexbuffer = NULL;
8472         rsurface.batchnormal3f_bufferoffset = 0;
8473         rsurface.batchlightmapcolor4f = NULL;
8474         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8475         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8476         rsurface.batchtexcoordtexture2f = NULL;
8477         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8478         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8479         rsurface.batchtexcoordlightmap2f = NULL;
8480         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8481         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8482         rsurface.batchvertexmesh = NULL;
8483         rsurface.batchvertexmeshbuffer = NULL;
8484         rsurface.batchvertex3fbuffer = NULL;
8485         rsurface.batchelement3i = NULL;
8486         rsurface.batchelement3i_indexbuffer = NULL;
8487         rsurface.batchelement3i_bufferoffset = 0;
8488         rsurface.batchelement3s = NULL;
8489         rsurface.batchelement3s_indexbuffer = NULL;
8490         rsurface.batchelement3s_bufferoffset = 0;
8491         rsurface.passcolor4f = NULL;
8492         rsurface.passcolor4f_vertexbuffer = NULL;
8493         rsurface.passcolor4f_bufferoffset = 0;
8494         rsurface.forcecurrenttextureupdate = true;
8495
8496         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8497         {
8498                 if ((wantnormals || wanttangents) && !normal3f)
8499                 {
8500                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8501                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8502                 }
8503                 if (wanttangents && !svector3f)
8504                 {
8505                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8506                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8507                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8508                 }
8509         }
8510 }
8511
8512 float RSurf_FogPoint(const float *v)
8513 {
8514         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8515         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8516         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8517         float FogHeightFade = r_refdef.fogheightfade;
8518         float fogfrac;
8519         unsigned int fogmasktableindex;
8520         if (r_refdef.fogplaneviewabove)
8521                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8522         else
8523                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8524         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8525         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8526 }
8527
8528 float RSurf_FogVertex(const float *v)
8529 {
8530         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8531         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8532         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8533         float FogHeightFade = rsurface.fogheightfade;
8534         float fogfrac;
8535         unsigned int fogmasktableindex;
8536         if (r_refdef.fogplaneviewabove)
8537                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8538         else
8539                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8540         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8541         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8542 }
8543
8544 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8545 {
8546         int i;
8547         for (i = 0;i < numelements;i++)
8548                 outelement3i[i] = inelement3i[i] + adjust;
8549 }
8550
8551 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8552 extern cvar_t gl_vbo;
8553 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8554 {
8555         int deformindex;
8556         int firsttriangle;
8557         int numtriangles;
8558         int firstvertex;
8559         int endvertex;
8560         int numvertices;
8561         int surfacefirsttriangle;
8562         int surfacenumtriangles;
8563         int surfacefirstvertex;
8564         int surfaceendvertex;
8565         int surfacenumvertices;
8566         int batchnumvertices;
8567         int batchnumtriangles;
8568         int needsupdate;
8569         int i, j;
8570         qboolean gaps;
8571         qboolean dynamicvertex;
8572         float amplitude;
8573         float animpos;
8574         float scale;
8575         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8576         float waveparms[4];
8577         q3shaderinfo_deform_t *deform;
8578         const msurface_t *surface, *firstsurface;
8579         r_vertexmesh_t *vertexmesh;
8580         if (!texturenumsurfaces)
8581                 return;
8582         // find vertex range of this surface batch
8583         gaps = false;
8584         firstsurface = texturesurfacelist[0];
8585         firsttriangle = firstsurface->num_firsttriangle;
8586         batchnumvertices = 0;
8587         batchnumtriangles = 0;
8588         firstvertex = endvertex = firstsurface->num_firstvertex;
8589         for (i = 0;i < texturenumsurfaces;i++)
8590         {
8591                 surface = texturesurfacelist[i];
8592                 if (surface != firstsurface + i)
8593                         gaps = true;
8594                 surfacefirstvertex = surface->num_firstvertex;
8595                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8596                 surfacenumvertices = surface->num_vertices;
8597                 surfacenumtriangles = surface->num_triangles;
8598                 if (firstvertex > surfacefirstvertex)
8599                         firstvertex = surfacefirstvertex;
8600                 if (endvertex < surfaceendvertex)
8601                         endvertex = surfaceendvertex;
8602                 batchnumvertices += surfacenumvertices;
8603                 batchnumtriangles += surfacenumtriangles;
8604         }
8605
8606         // we now know the vertex range used, and if there are any gaps in it
8607         rsurface.batchfirstvertex = firstvertex;
8608         rsurface.batchnumvertices = endvertex - firstvertex;
8609         rsurface.batchfirsttriangle = firsttriangle;
8610         rsurface.batchnumtriangles = batchnumtriangles;
8611
8612         // this variable holds flags for which properties have been updated that
8613         // may require regenerating vertexmesh array...
8614         needsupdate = 0;
8615
8616         // check if any dynamic vertex processing must occur
8617         dynamicvertex = false;
8618
8619         // if there is a chance of animated vertex colors, it's a dynamic batch
8620         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8621         {
8622                 dynamicvertex = true;
8623                 batchneed |= BATCHNEED_NOGAPS;
8624                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8625         }
8626
8627         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8628         {
8629                 switch (deform->deform)
8630                 {
8631                 default:
8632                 case Q3DEFORM_PROJECTIONSHADOW:
8633                 case Q3DEFORM_TEXT0:
8634                 case Q3DEFORM_TEXT1:
8635                 case Q3DEFORM_TEXT2:
8636                 case Q3DEFORM_TEXT3:
8637                 case Q3DEFORM_TEXT4:
8638                 case Q3DEFORM_TEXT5:
8639                 case Q3DEFORM_TEXT6:
8640                 case Q3DEFORM_TEXT7:
8641                 case Q3DEFORM_NONE:
8642                         break;
8643                 case Q3DEFORM_AUTOSPRITE:
8644                         dynamicvertex = true;
8645                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8646                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8647                         break;
8648                 case Q3DEFORM_AUTOSPRITE2:
8649                         dynamicvertex = true;
8650                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8652                         break;
8653                 case Q3DEFORM_NORMAL:
8654                         dynamicvertex = true;
8655                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8657                         break;
8658                 case Q3DEFORM_WAVE:
8659                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8660                                 break; // if wavefunc is a nop, ignore this transform
8661                         dynamicvertex = true;
8662                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8663                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8664                         break;
8665                 case Q3DEFORM_BULGE:
8666                         dynamicvertex = true;
8667                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8668                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8669                         break;
8670                 case Q3DEFORM_MOVE:
8671                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8672                                 break; // if wavefunc is a nop, ignore this transform
8673                         dynamicvertex = true;
8674                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8675                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8676                         break;
8677                 }
8678         }
8679         switch(rsurface.texture->tcgen.tcgen)
8680         {
8681         default:
8682         case Q3TCGEN_TEXTURE:
8683                 break;
8684         case Q3TCGEN_LIGHTMAP:
8685                 dynamicvertex = true;
8686                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8687                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8688                 break;
8689         case Q3TCGEN_VECTOR:
8690                 dynamicvertex = true;
8691                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8692                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8693                 break;
8694         case Q3TCGEN_ENVIRONMENT:
8695                 dynamicvertex = true;
8696                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8697                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8698                 break;
8699         }
8700         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8701         {
8702                 dynamicvertex = true;
8703                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8704                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8705         }
8706
8707         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8708         {
8709                 dynamicvertex = true;
8710                 batchneed |= BATCHNEED_NOGAPS;
8711                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8712         }
8713
8714         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8715         {
8716                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8717                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8718                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8719                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8720                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8721                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8722                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8723         }
8724
8725         // when the model data has no vertex buffer (dynamic mesh), we need to
8726         // eliminate gaps
8727         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8728                 batchneed |= BATCHNEED_NOGAPS;
8729
8730         // if needsupdate, we have to do a dynamic vertex batch for sure
8731         if (needsupdate & batchneed)
8732                 dynamicvertex = true;
8733
8734         // see if we need to build vertexmesh from arrays
8735         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8736                 dynamicvertex = true;
8737
8738         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8739         // also some drivers strongly dislike firstvertex
8740         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8741                 dynamicvertex = true;
8742
8743         rsurface.batchvertex3f = rsurface.modelvertex3f;
8744         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8745         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8746         rsurface.batchsvector3f = rsurface.modelsvector3f;
8747         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8748         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8749         rsurface.batchtvector3f = rsurface.modeltvector3f;
8750         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8751         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8752         rsurface.batchnormal3f = rsurface.modelnormal3f;
8753         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8754         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8755         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8756         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8757         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8758         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8759         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8760         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8761         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8762         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8763         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8764         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8765         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8766         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8767         rsurface.batchelement3i = rsurface.modelelement3i;
8768         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8769         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8770         rsurface.batchelement3s = rsurface.modelelement3s;
8771         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8772         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8773
8774         // if any dynamic vertex processing has to occur in software, we copy the
8775         // entire surface list together before processing to rebase the vertices
8776         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8777         //
8778         // if any gaps exist and we do not have a static vertex buffer, we have to
8779         // copy the surface list together to avoid wasting upload bandwidth on the
8780         // vertices in the gaps.
8781         //
8782         // if gaps exist and we have a static vertex buffer, we still have to
8783         // combine the index buffer ranges into one dynamic index buffer.
8784         //
8785         // in all cases we end up with data that can be drawn in one call.
8786
8787         if (!dynamicvertex)
8788         {
8789                 // static vertex data, just set pointers...
8790                 rsurface.batchgeneratedvertex = false;
8791                 // if there are gaps, we want to build a combined index buffer,
8792                 // otherwise use the original static buffer with an appropriate offset
8793                 if (gaps)
8794                 {
8795                         // build a new triangle elements array for this batch
8796                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8797                         rsurface.batchfirsttriangle = 0;
8798                         numtriangles = 0;
8799                         for (i = 0;i < texturenumsurfaces;i++)
8800                         {
8801                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8802                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8803                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8804                                 numtriangles += surfacenumtriangles;
8805                         }
8806                         rsurface.batchelement3i_indexbuffer = NULL;
8807                         rsurface.batchelement3i_bufferoffset = 0;
8808                         rsurface.batchelement3s = NULL;
8809                         rsurface.batchelement3s_indexbuffer = NULL;
8810                         rsurface.batchelement3s_bufferoffset = 0;
8811                         if (endvertex <= 65536)
8812                         {
8813                                 // make a 16bit (unsigned short) index array if possible
8814                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8815                                 for (i = 0;i < numtriangles*3;i++)
8816                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8817                         }
8818                 }
8819                 return;
8820         }
8821
8822         // something needs software processing, do it for real...
8823         // we only directly handle separate array data in this case and then
8824         // generate interleaved data if needed...
8825         rsurface.batchgeneratedvertex = true;
8826
8827         // now copy the vertex data into a combined array and make an index array
8828         // (this is what Quake3 does all the time)
8829         //if (gaps || rsurface.batchfirstvertex)
8830         {
8831                 rsurface.batchvertex3fbuffer = NULL;
8832                 rsurface.batchvertexmesh = NULL;
8833                 rsurface.batchvertexmeshbuffer = NULL;
8834                 rsurface.batchvertex3f = NULL;
8835                 rsurface.batchvertex3f_vertexbuffer = NULL;
8836                 rsurface.batchvertex3f_bufferoffset = 0;
8837                 rsurface.batchsvector3f = NULL;
8838                 rsurface.batchsvector3f_vertexbuffer = NULL;
8839                 rsurface.batchsvector3f_bufferoffset = 0;
8840                 rsurface.batchtvector3f = NULL;
8841                 rsurface.batchtvector3f_vertexbuffer = NULL;
8842                 rsurface.batchtvector3f_bufferoffset = 0;
8843                 rsurface.batchnormal3f = NULL;
8844                 rsurface.batchnormal3f_vertexbuffer = NULL;
8845                 rsurface.batchnormal3f_bufferoffset = 0;
8846                 rsurface.batchlightmapcolor4f = NULL;
8847                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8848                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8849                 rsurface.batchtexcoordtexture2f = NULL;
8850                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8851                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8852                 rsurface.batchtexcoordlightmap2f = NULL;
8853                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8854                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8855                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8856                 rsurface.batchelement3i_indexbuffer = NULL;
8857                 rsurface.batchelement3i_bufferoffset = 0;
8858                 rsurface.batchelement3s = NULL;
8859                 rsurface.batchelement3s_indexbuffer = NULL;
8860                 rsurface.batchelement3s_bufferoffset = 0;
8861                 // we'll only be setting up certain arrays as needed
8862                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8863                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8864                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8865                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8866                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8867                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8869                 {
8870                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8872                 }
8873                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8874                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8875                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8876                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8877                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8878                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8879                 numvertices = 0;
8880                 numtriangles = 0;
8881                 for (i = 0;i < texturenumsurfaces;i++)
8882                 {
8883                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8884                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8885                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8886                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8887                         // copy only the data requested
8888                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8889                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8890                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8891                         {
8892                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8893                                 {
8894                                         if (rsurface.batchvertex3f)
8895                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8896                                         else
8897                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8898                                 }
8899                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8900                                 {
8901                                         if (rsurface.modelnormal3f)
8902                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8903                                         else
8904                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8905                                 }
8906                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8907                                 {
8908                                         if (rsurface.modelsvector3f)
8909                                         {
8910                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8911                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8912                                         }
8913                                         else
8914                                         {
8915                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8916                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8917                                         }
8918                                 }
8919                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8920                                 {
8921                                         if (rsurface.modellightmapcolor4f)
8922                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8923                                         else
8924                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8925                                 }
8926                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8927                                 {
8928                                         if (rsurface.modeltexcoordtexture2f)
8929                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8930                                         else
8931                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8932                                 }
8933                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8934                                 {
8935                                         if (rsurface.modeltexcoordlightmap2f)
8936                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8937                                         else
8938                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8939                                 }
8940                         }
8941                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8942                         numvertices += surfacenumvertices;
8943                         numtriangles += surfacenumtriangles;
8944                 }
8945
8946                 // generate a 16bit index array as well if possible
8947                 // (in general, dynamic batches fit)
8948                 if (numvertices <= 65536)
8949                 {
8950                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8951                         for (i = 0;i < numtriangles*3;i++)
8952                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8953                 }
8954
8955                 // since we've copied everything, the batch now starts at 0
8956                 rsurface.batchfirstvertex = 0;
8957                 rsurface.batchnumvertices = batchnumvertices;
8958                 rsurface.batchfirsttriangle = 0;
8959                 rsurface.batchnumtriangles = batchnumtriangles;
8960         }
8961
8962         // q1bsp surfaces rendered in vertex color mode have to have colors
8963         // calculated based on lightstyles
8964         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8965         {
8966                 // generate color arrays for the surfaces in this list
8967                 int c[4];
8968                 int scale;
8969                 int size3;
8970                 const int *offsets;
8971                 const unsigned char *lm;
8972                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8973                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8974                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8975                 numvertices = 0;
8976                 for (i = 0;i < texturenumsurfaces;i++)
8977                 {
8978                         surface = texturesurfacelist[i];
8979                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8980                         surfacenumvertices = surface->num_vertices;
8981                         if (surface->lightmapinfo->samples)
8982                         {
8983                                 for (j = 0;j < surfacenumvertices;j++)
8984                                 {
8985                                         lm = surface->lightmapinfo->samples + offsets[j];
8986                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8987                                         VectorScale(lm, scale, c);
8988                                         if (surface->lightmapinfo->styles[1] != 255)
8989                                         {
8990                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8991                                                 lm += size3;
8992                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8993                                                 VectorMA(c, scale, lm, c);
8994                                                 if (surface->lightmapinfo->styles[2] != 255)
8995                                                 {
8996                                                         lm += size3;
8997                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8998                                                         VectorMA(c, scale, lm, c);
8999                                                         if (surface->lightmapinfo->styles[3] != 255)
9000                                                         {
9001                                                                 lm += size3;
9002                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9003                                                                 VectorMA(c, scale, lm, c);
9004                                                         }
9005                                                 }
9006                                         }
9007                                         c[0] >>= 7;
9008                                         c[1] >>= 7;
9009                                         c[2] >>= 7;
9010                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
9011                                         numvertices++;
9012                                 }
9013                         }
9014                         else
9015                         {
9016                                 for (j = 0;j < surfacenumvertices;j++)
9017                                 {
9018                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9019                                         numvertices++;
9020                                 }
9021                         }
9022                 }
9023         }
9024
9025         // if vertices are deformed (sprite flares and things in maps, possibly
9026         // water waves, bulges and other deformations), modify the copied vertices
9027         // in place
9028         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9029         {
9030                 switch (deform->deform)
9031                 {
9032                 default:
9033                 case Q3DEFORM_PROJECTIONSHADOW:
9034                 case Q3DEFORM_TEXT0:
9035                 case Q3DEFORM_TEXT1:
9036                 case Q3DEFORM_TEXT2:
9037                 case Q3DEFORM_TEXT3:
9038                 case Q3DEFORM_TEXT4:
9039                 case Q3DEFORM_TEXT5:
9040                 case Q3DEFORM_TEXT6:
9041                 case Q3DEFORM_TEXT7:
9042                 case Q3DEFORM_NONE:
9043                         break;
9044                 case Q3DEFORM_AUTOSPRITE:
9045                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9046                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9047                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9048                         VectorNormalize(newforward);
9049                         VectorNormalize(newright);
9050                         VectorNormalize(newup);
9051 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9052 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9053 //                      rsurface.batchvertex3f_bufferoffset = 0;
9054 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9055 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9056 //                      rsurface.batchsvector3f_bufferoffset = 0;
9057 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9058 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9059 //                      rsurface.batchtvector3f_bufferoffset = 0;
9060 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9061 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9062 //                      rsurface.batchnormal3f_bufferoffset = 0;
9063                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9064                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9065                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9066                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9067                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9068                         // a single autosprite surface can contain multiple sprites...
9069                         for (j = 0;j < batchnumvertices - 3;j += 4)
9070                         {
9071                                 VectorClear(center);
9072                                 for (i = 0;i < 4;i++)
9073                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9074                                 VectorScale(center, 0.25f, center);
9075                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9076                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9077                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9078                                 for (i = 0;i < 4;i++)
9079                                 {
9080                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9081                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9082                                 }
9083                         }
9084                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9085                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9086                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9087                         break;
9088                 case Q3DEFORM_AUTOSPRITE2:
9089                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9090                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9091                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9092                         VectorNormalize(newforward);
9093                         VectorNormalize(newright);
9094                         VectorNormalize(newup);
9095 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9096 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9097 //                      rsurface.batchvertex3f_bufferoffset = 0;
9098                         {
9099                                 const float *v1, *v2;
9100                                 vec3_t start, end;
9101                                 float f, l;
9102                                 struct
9103                                 {
9104                                         float length2;
9105                                         const float *v1;
9106                                         const float *v2;
9107                                 }
9108                                 shortest[2];
9109                                 memset(shortest, 0, sizeof(shortest));
9110                                 // a single autosprite surface can contain multiple sprites...
9111                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9112                                 {
9113                                         VectorClear(center);
9114                                         for (i = 0;i < 4;i++)
9115                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9116                                         VectorScale(center, 0.25f, center);
9117                                         // find the two shortest edges, then use them to define the
9118                                         // axis vectors for rotating around the central axis
9119                                         for (i = 0;i < 6;i++)
9120                                         {
9121                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9122                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9123                                                 l = VectorDistance2(v1, v2);
9124                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9125                                                 if (v1[2] != v2[2])
9126                                                         l += (1.0f / 1024.0f);
9127                                                 if (shortest[0].length2 > l || i == 0)
9128                                                 {
9129                                                         shortest[1] = shortest[0];
9130                                                         shortest[0].length2 = l;
9131                                                         shortest[0].v1 = v1;
9132                                                         shortest[0].v2 = v2;
9133                                                 }
9134                                                 else if (shortest[1].length2 > l || i == 1)
9135                                                 {
9136                                                         shortest[1].length2 = l;
9137                                                         shortest[1].v1 = v1;
9138                                                         shortest[1].v2 = v2;
9139                                                 }
9140                                         }
9141                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9142                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9143                                         // this calculates the right vector from the shortest edge
9144                                         // and the up vector from the edge midpoints
9145                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9146                                         VectorNormalize(right);
9147                                         VectorSubtract(end, start, up);
9148                                         VectorNormalize(up);
9149                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9150                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9151                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9152                                         VectorNegate(forward, forward);
9153                                         VectorReflect(forward, 0, up, forward);
9154                                         VectorNormalize(forward);
9155                                         CrossProduct(up, forward, newright);
9156                                         VectorNormalize(newright);
9157                                         // rotate the quad around the up axis vector, this is made
9158                                         // especially easy by the fact we know the quad is flat,
9159                                         // so we only have to subtract the center position and
9160                                         // measure distance along the right vector, and then
9161                                         // multiply that by the newright vector and add back the
9162                                         // center position
9163                                         // we also need to subtract the old position to undo the
9164                                         // displacement from the center, which we do with a
9165                                         // DotProduct, the subtraction/addition of center is also
9166                                         // optimized into DotProducts here
9167                                         l = DotProduct(right, center);
9168                                         for (i = 0;i < 4;i++)
9169                                         {
9170                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9171                                                 f = DotProduct(right, v1) - l;
9172                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9173                                         }
9174                                 }
9175                         }
9176                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9177                         {
9178 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9179 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9180 //                              rsurface.batchnormal3f_bufferoffset = 0;
9181                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9182                         }
9183                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9184                         {
9185 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9186 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9187 //                              rsurface.batchsvector3f_bufferoffset = 0;
9188 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9189 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9190 //                              rsurface.batchtvector3f_bufferoffset = 0;
9191                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9192                         }
9193                         break;
9194                 case Q3DEFORM_NORMAL:
9195                         // deform the normals to make reflections wavey
9196                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9197                         rsurface.batchnormal3f_vertexbuffer = NULL;
9198                         rsurface.batchnormal3f_bufferoffset = 0;
9199                         for (j = 0;j < batchnumvertices;j++)
9200                         {
9201                                 float vertex[3];
9202                                 float *normal = rsurface.batchnormal3f + 3*j;
9203                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9204                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9205                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9206                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9207                                 VectorNormalize(normal);
9208                         }
9209                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9210                         {
9211 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9212 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9213 //                              rsurface.batchsvector3f_bufferoffset = 0;
9214 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9215 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9216 //                              rsurface.batchtvector3f_bufferoffset = 0;
9217                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9218                         }
9219                         break;
9220                 case Q3DEFORM_WAVE:
9221                         // deform vertex array to make wavey water and flags and such
9222                         waveparms[0] = deform->waveparms[0];
9223                         waveparms[1] = deform->waveparms[1];
9224                         waveparms[2] = deform->waveparms[2];
9225                         waveparms[3] = deform->waveparms[3];
9226                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9227                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9228                         // this is how a divisor of vertex influence on deformation
9229                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9230                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9231 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9232 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9233 //                      rsurface.batchvertex3f_bufferoffset = 0;
9234 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9235 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9236 //                      rsurface.batchnormal3f_bufferoffset = 0;
9237                         for (j = 0;j < batchnumvertices;j++)
9238                         {
9239                                 // if the wavefunc depends on time, evaluate it per-vertex
9240                                 if (waveparms[3])
9241                                 {
9242                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9243                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9244                                 }
9245                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9246                         }
9247                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9248                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9249                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9250                         {
9251 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9252 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9253 //                              rsurface.batchsvector3f_bufferoffset = 0;
9254 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9255 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9256 //                              rsurface.batchtvector3f_bufferoffset = 0;
9257                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9258                         }
9259                         break;
9260                 case Q3DEFORM_BULGE:
9261                         // deform vertex array to make the surface have moving bulges
9262 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9263 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9264 //                      rsurface.batchvertex3f_bufferoffset = 0;
9265 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9266 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9267 //                      rsurface.batchnormal3f_bufferoffset = 0;
9268                         for (j = 0;j < batchnumvertices;j++)
9269                         {
9270                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9271                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9272                         }
9273                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9274                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9275                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9276                         {
9277 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9278 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9279 //                              rsurface.batchsvector3f_bufferoffset = 0;
9280 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9281 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9282 //                              rsurface.batchtvector3f_bufferoffset = 0;
9283                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9284                         }
9285                         break;
9286                 case Q3DEFORM_MOVE:
9287                         // deform vertex array
9288                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9289                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9290                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9291                         VectorScale(deform->parms, scale, waveparms);
9292 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9293 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9294 //                      rsurface.batchvertex3f_bufferoffset = 0;
9295                         for (j = 0;j < batchnumvertices;j++)
9296                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9297                         break;
9298                 }
9299         }
9300
9301         // generate texcoords based on the chosen texcoord source
9302         switch(rsurface.texture->tcgen.tcgen)
9303         {
9304         default:
9305         case Q3TCGEN_TEXTURE:
9306                 break;
9307         case Q3TCGEN_LIGHTMAP:
9308 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9309 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9310 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9311                 if (rsurface.batchtexcoordlightmap2f)
9312                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9313                 break;
9314         case Q3TCGEN_VECTOR:
9315 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9316 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9317 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9318                 for (j = 0;j < batchnumvertices;j++)
9319                 {
9320                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9321                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9322                 }
9323                 break;
9324         case Q3TCGEN_ENVIRONMENT:
9325                 // make environment reflections using a spheremap
9326                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9327                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9328                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9329                 for (j = 0;j < batchnumvertices;j++)
9330                 {
9331                         // identical to Q3A's method, but executed in worldspace so
9332                         // carried models can be shiny too
9333
9334                         float viewer[3], d, reflected[3], worldreflected[3];
9335
9336                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9337                         // VectorNormalize(viewer);
9338
9339                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9340
9341                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9342                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9343                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9344                         // note: this is proportinal to viewer, so we can normalize later
9345
9346                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9347                         VectorNormalize(worldreflected);
9348
9349                         // note: this sphere map only uses world x and z!
9350                         // so positive and negative y will LOOK THE SAME.
9351                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9352                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9353                 }
9354                 break;
9355         }
9356         // the only tcmod that needs software vertex processing is turbulent, so
9357         // check for it here and apply the changes if needed
9358         // and we only support that as the first one
9359         // (handling a mixture of turbulent and other tcmods would be problematic
9360         //  without punting it entirely to a software path)
9361         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9362         {
9363                 amplitude = rsurface.texture->tcmods[0].parms[1];
9364                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9365 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9366 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9367 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9368                 for (j = 0;j < batchnumvertices;j++)
9369                 {
9370                         rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9371                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9372                 }
9373         }
9374
9375         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9376         {
9377                 // convert the modified arrays to vertex structs
9378 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9379 //              rsurface.batchvertexmeshbuffer = NULL;
9380                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9381                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9382                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9383                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9384                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9385                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9386                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9387                 {
9388                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9389                         {
9390                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9391                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9392                         }
9393                 }
9394                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9395                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9396                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9397                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9398                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9399                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9400                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9401                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9402                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9403         }
9404 }
9405
9406 void RSurf_DrawBatch(void)
9407 {
9408         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9409         // through the pipeline, killing it earlier in the pipeline would have
9410         // per-surface overhead rather than per-batch overhead, so it's best to
9411         // reject it here, before it hits glDraw.
9412         if (rsurface.batchnumtriangles == 0)
9413                 return;
9414 #if 0
9415         // batch debugging code
9416         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9417         {
9418                 int i;
9419                 int j;
9420                 int c;
9421                 const int *e;
9422                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9423                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9424                 {
9425                         c = e[i];
9426                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9427                         {
9428                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9429                                 {
9430                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9431                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
9432                                         break;
9433                                 }
9434                         }
9435                 }
9436         }
9437 #endif
9438         R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
9439 }
9440
9441 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9442 {
9443         // pick the closest matching water plane
9444         int planeindex, vertexindex, bestplaneindex = -1;
9445         float d, bestd;
9446         vec3_t vert;
9447         const float *v;
9448         r_waterstate_waterplane_t *p;
9449         qboolean prepared = false;
9450         bestd = 0;
9451         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9452         {
9453                 if(p->camera_entity != rsurface.texture->camera_entity)
9454                         continue;
9455                 d = 0;
9456                 if(!prepared)
9457                 {
9458                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9459                         prepared = true;
9460                         if(rsurface.batchnumvertices == 0)
9461                                 break;
9462                 }
9463                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9464                 {
9465                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9466                         d += fabs(PlaneDiff(vert, &p->plane));
9467                 }
9468                 if (bestd > d || bestplaneindex < 0)
9469                 {
9470                         bestd = d;
9471                         bestplaneindex = planeindex;
9472                 }
9473         }
9474         return bestplaneindex;
9475         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9476         // this situation though, as it might be better to render single larger
9477         // batches with useless stuff (backface culled for example) than to
9478         // render multiple smaller batches
9479 }
9480
9481 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9482 {
9483         int i;
9484         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9485         rsurface.passcolor4f_vertexbuffer = 0;
9486         rsurface.passcolor4f_bufferoffset = 0;
9487         for (i = 0;i < rsurface.batchnumvertices;i++)
9488                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9489 }
9490
9491 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9492 {
9493         int i;
9494         float f;
9495         const float *v;
9496         const float *c;
9497         float *c2;
9498         if (rsurface.passcolor4f)
9499         {
9500                 // generate color arrays
9501                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9502                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9503                 rsurface.passcolor4f_vertexbuffer = 0;
9504                 rsurface.passcolor4f_bufferoffset = 0;
9505                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9506                 {
9507                         f = RSurf_FogVertex(v);
9508                         c2[0] = c[0] * f;
9509                         c2[1] = c[1] * f;
9510                         c2[2] = c[2] * f;
9511                         c2[3] = c[3];
9512                 }
9513         }
9514         else
9515         {
9516                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9517                 rsurface.passcolor4f_vertexbuffer = 0;
9518                 rsurface.passcolor4f_bufferoffset = 0;
9519                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9520                 {
9521                         f = RSurf_FogVertex(v);
9522                         c2[0] = f;
9523                         c2[1] = f;
9524                         c2[2] = f;
9525                         c2[3] = 1;
9526                 }
9527         }
9528 }
9529
9530 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9531 {
9532         int i;
9533         float f;
9534         const float *v;
9535         const float *c;
9536         float *c2;
9537         if (!rsurface.passcolor4f)
9538                 return;
9539         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9540         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9541         rsurface.passcolor4f_vertexbuffer = 0;
9542         rsurface.passcolor4f_bufferoffset = 0;
9543         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9544         {
9545                 f = RSurf_FogVertex(v);
9546                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9547                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9548                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9549                 c2[3] = c[3];
9550         }
9551 }
9552
9553 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9554 {
9555         int i;
9556         const float *c;
9557         float *c2;
9558         if (!rsurface.passcolor4f)
9559                 return;
9560         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9561         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9562         rsurface.passcolor4f_vertexbuffer = 0;
9563         rsurface.passcolor4f_bufferoffset = 0;
9564         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9565         {
9566                 c2[0] = c[0] * r;
9567                 c2[1] = c[1] * g;
9568                 c2[2] = c[2] * b;
9569                 c2[3] = c[3] * a;
9570         }
9571 }
9572
9573 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9574 {
9575         int i;
9576         const float *c;
9577         float *c2;
9578         if (!rsurface.passcolor4f)
9579                 return;
9580         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9581         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9582         rsurface.passcolor4f_vertexbuffer = 0;
9583         rsurface.passcolor4f_bufferoffset = 0;
9584         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9585         {
9586                 c2[0] = c[0] + r_refdef.scene.ambient;
9587                 c2[1] = c[1] + r_refdef.scene.ambient;
9588                 c2[2] = c[2] + r_refdef.scene.ambient;
9589                 c2[3] = c[3];
9590         }
9591 }
9592
9593 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9594 {
9595         // TODO: optimize
9596         rsurface.passcolor4f = NULL;
9597         rsurface.passcolor4f_vertexbuffer = 0;
9598         rsurface.passcolor4f_bufferoffset = 0;
9599         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9600         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9601         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9602         GL_Color(r, g, b, a);
9603         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9604         RSurf_DrawBatch();
9605 }
9606
9607 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9608 {
9609         // TODO: optimize applyfog && applycolor case
9610         // just apply fog if necessary, and tint the fog color array if necessary
9611         rsurface.passcolor4f = NULL;
9612         rsurface.passcolor4f_vertexbuffer = 0;
9613         rsurface.passcolor4f_bufferoffset = 0;
9614         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9615         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9616         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9617         GL_Color(r, g, b, a);
9618         RSurf_DrawBatch();
9619 }
9620
9621 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9622 {
9623         // TODO: optimize
9624         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9625         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9626         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9627         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9628         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9629         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9630         GL_Color(r, g, b, a);
9631         RSurf_DrawBatch();
9632 }
9633
9634 static void RSurf_DrawBatch_GL11_ClampColor(void)
9635 {
9636         int i;
9637         const float *c1;
9638         float *c2;
9639         if (!rsurface.passcolor4f)
9640                 return;
9641         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9642         {
9643                 c2[0] = bound(0.0f, c1[0], 1.0f);
9644                 c2[1] = bound(0.0f, c1[1], 1.0f);
9645                 c2[2] = bound(0.0f, c1[2], 1.0f);
9646                 c2[3] = bound(0.0f, c1[3], 1.0f);
9647         }
9648 }
9649
9650 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9651 {
9652         int i;
9653         float f;
9654         const float *v;
9655         const float *n;
9656         float *c;
9657         //vec3_t eyedir;
9658
9659         // fake shading
9660         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9661         rsurface.passcolor4f_vertexbuffer = 0;
9662         rsurface.passcolor4f_bufferoffset = 0;
9663         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9664         {
9665                 f = -DotProduct(r_refdef.view.forward, n);
9666                 f = max(0, f);
9667                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9668                 f *= r_refdef.lightmapintensity;
9669                 Vector4Set(c, f, f, f, 1);
9670         }
9671 }
9672
9673 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9674 {
9675         RSurf_DrawBatch_GL11_ApplyFakeLight();
9676         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9677         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9678         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9679         GL_Color(r, g, b, a);
9680         RSurf_DrawBatch();
9681 }
9682
9683 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9684 {
9685         int i;
9686         float f;
9687         float alpha;
9688         const float *v;
9689         const float *n;
9690         float *c;
9691         vec3_t ambientcolor;
9692         vec3_t diffusecolor;
9693         vec3_t lightdir;
9694         // TODO: optimize
9695         // model lighting
9696         VectorCopy(rsurface.modellight_lightdir, lightdir);
9697         f = 0.5f * r_refdef.lightmapintensity;
9698         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9699         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9700         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9701         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9702         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9703         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9704         alpha = *a;
9705         if (VectorLength2(diffusecolor) > 0)
9706         {
9707                 // q3-style directional shading
9708                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9709                 rsurface.passcolor4f_vertexbuffer = 0;
9710                 rsurface.passcolor4f_bufferoffset = 0;
9711                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9712                 {
9713                         if ((f = DotProduct(n, lightdir)) > 0)
9714                                 VectorMA(ambientcolor, f, diffusecolor, c);
9715                         else
9716                                 VectorCopy(ambientcolor, c);
9717                         c[3] = alpha;
9718                 }
9719                 *r = 1;
9720                 *g = 1;
9721                 *b = 1;
9722                 *a = 1;
9723                 *applycolor = false;
9724         }
9725         else
9726         {
9727                 *r = ambientcolor[0];
9728                 *g = ambientcolor[1];
9729                 *b = ambientcolor[2];
9730                 rsurface.passcolor4f = NULL;
9731                 rsurface.passcolor4f_vertexbuffer = 0;
9732                 rsurface.passcolor4f_bufferoffset = 0;
9733         }
9734 }
9735
9736 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9737 {
9738         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9739         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9740         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9741         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9742         GL_Color(r, g, b, a);
9743         RSurf_DrawBatch();
9744 }
9745
9746 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9747 {
9748         int i;
9749         float f;
9750         const float *v;
9751         float *c;
9752
9753         // fake shading
9754         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9755         rsurface.passcolor4f_vertexbuffer = 0;
9756         rsurface.passcolor4f_bufferoffset = 0;
9757
9758         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9759         {
9760                 f = 1 - RSurf_FogVertex(v);
9761                 c[0] = r;
9762                 c[1] = g;
9763                 c[2] = b;
9764                 c[3] = f * a;
9765         }
9766 }
9767
9768 void RSurf_SetupDepthAndCulling(void)
9769 {
9770         // submodels are biased to avoid z-fighting with world surfaces that they
9771         // may be exactly overlapping (avoids z-fighting artifacts on certain
9772         // doors and things in Quake maps)
9773         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9774         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9775         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9776         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9777 }
9778
9779 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9780 {
9781         // transparent sky would be ridiculous
9782         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9783                 return;
9784         R_SetupShader_Generic_NoTexture(false, false);
9785         skyrenderlater = true;
9786         RSurf_SetupDepthAndCulling();
9787         GL_DepthMask(true);
9788         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9789         // skymasking on them, and Quake3 never did sky masking (unlike
9790         // software Quake and software Quake2), so disable the sky masking
9791         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9792         // and skymasking also looks very bad when noclipping outside the
9793         // level, so don't use it then either.
9794         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9795         {
9796                 R_Mesh_ResetTextureState();
9797                 if (skyrendermasked)
9798                 {
9799                         R_SetupShader_DepthOrShadow(false, false);
9800                         // depth-only (masking)
9801                         GL_ColorMask(0,0,0,0);
9802                         // just to make sure that braindead drivers don't draw
9803                         // anything despite that colormask...
9804                         GL_BlendFunc(GL_ZERO, GL_ONE);
9805                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806                         if (rsurface.batchvertex3fbuffer)
9807                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9808                         else
9809                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9810                 }
9811                 else
9812                 {
9813                         R_SetupShader_Generic_NoTexture(false, false);
9814                         // fog sky
9815                         GL_BlendFunc(GL_ONE, GL_ZERO);
9816                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9817                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9818                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9819                 }
9820                 RSurf_DrawBatch();
9821                 if (skyrendermasked)
9822                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9823         }
9824         R_Mesh_ResetTextureState();
9825         GL_Color(1, 1, 1, 1);
9826 }
9827
9828 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9829 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9830 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9831 {
9832         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9833                 return;
9834         if (prepass)
9835         {
9836                 // render screenspace normalmap to texture
9837                 GL_DepthMask(true);
9838                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9839                 RSurf_DrawBatch();
9840                 return;
9841         }
9842
9843         // bind lightmap texture
9844
9845         // water/refraction/reflection/camera surfaces have to be handled specially
9846         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9847         {
9848                 int start, end, startplaneindex;
9849                 for (start = 0;start < texturenumsurfaces;start = end)
9850                 {
9851                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9852                         if(startplaneindex < 0)
9853                         {
9854                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9855                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9856                                 end = start + 1;
9857                                 continue;
9858                         }
9859                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9860                                 ;
9861                         // now that we have a batch using the same planeindex, render it
9862                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9863                         {
9864                                 // render water or distortion background
9865                                 GL_DepthMask(true);
9866                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9867                                 RSurf_DrawBatch();
9868                                 // blend surface on top
9869                                 GL_DepthMask(false);
9870                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9871                                 RSurf_DrawBatch();
9872                         }
9873                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9874                         {
9875                                 // render surface with reflection texture as input
9876                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9877                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9878                                 RSurf_DrawBatch();
9879                         }
9880                 }
9881                 return;
9882         }
9883
9884         // render surface batch normally
9885         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9886         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9887         RSurf_DrawBatch();
9888 }
9889
9890 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9891 {
9892         // OpenGL 1.3 path - anything not completely ancient
9893         qboolean applycolor;
9894         qboolean applyfog;
9895         int layerindex;
9896         const texturelayer_t *layer;
9897         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9898         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9899
9900         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9901         {
9902                 vec4_t layercolor;
9903                 int layertexrgbscale;
9904                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9905                 {
9906                         if (layerindex == 0)
9907                                 GL_AlphaTest(true);
9908                         else
9909                         {
9910                                 GL_AlphaTest(false);
9911                                 GL_DepthFunc(GL_EQUAL);
9912                         }
9913                 }
9914                 GL_DepthMask(layer->depthmask && writedepth);
9915                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9916                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9917                 {
9918                         layertexrgbscale = 4;
9919                         VectorScale(layer->color, 0.25f, layercolor);
9920                 }
9921                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9922                 {
9923                         layertexrgbscale = 2;
9924                         VectorScale(layer->color, 0.5f, layercolor);
9925                 }
9926                 else
9927                 {
9928                         layertexrgbscale = 1;
9929                         VectorScale(layer->color, 1.0f, layercolor);
9930                 }
9931                 layercolor[3] = layer->color[3];
9932                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9933                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9934                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9935                 switch (layer->type)
9936                 {
9937                 case TEXTURELAYERTYPE_LITTEXTURE:
9938                         // single-pass lightmapped texture with 2x rgbscale
9939                         R_Mesh_TexBind(0, r_texture_white);
9940                         R_Mesh_TexMatrix(0, NULL);
9941                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9942                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9943                         R_Mesh_TexBind(1, layer->texture);
9944                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9945                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9946                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9947                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9948                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9949                         else if (FAKELIGHT_ENABLED)
9950                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9951                         else if (rsurface.uselightmaptexture)
9952                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9953                         else
9954                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9955                         break;
9956                 case TEXTURELAYERTYPE_TEXTURE:
9957                         // singletexture unlit texture with transparency support
9958                         R_Mesh_TexBind(0, layer->texture);
9959                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9960                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9961                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9962                         R_Mesh_TexBind(1, 0);
9963                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9964                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9965                         break;
9966                 case TEXTURELAYERTYPE_FOG:
9967                         // singletexture fogging
9968                         if (layer->texture)
9969                         {
9970                                 R_Mesh_TexBind(0, layer->texture);
9971                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9972                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9973                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9974                         }
9975                         else
9976                         {
9977                                 R_Mesh_TexBind(0, 0);
9978                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9979                         }
9980                         R_Mesh_TexBind(1, 0);
9981                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9982                         // generate a color array for the fog pass
9983                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9984                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9985                         RSurf_DrawBatch();
9986                         break;
9987                 default:
9988                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9989                 }
9990         }
9991         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9992         {
9993                 GL_DepthFunc(GL_LEQUAL);
9994                 GL_AlphaTest(false);
9995         }
9996 }
9997
9998 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9999 {
10000         // OpenGL 1.1 - crusty old voodoo path
10001         qboolean applyfog;
10002         int layerindex;
10003         const texturelayer_t *layer;
10004         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10005         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10006
10007         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10008         {
10009                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10010                 {
10011                         if (layerindex == 0)
10012                                 GL_AlphaTest(true);
10013                         else
10014                         {
10015                                 GL_AlphaTest(false);
10016                                 GL_DepthFunc(GL_EQUAL);
10017                         }
10018                 }
10019                 GL_DepthMask(layer->depthmask && writedepth);
10020                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10021                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10022                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10023                 switch (layer->type)
10024                 {
10025                 case TEXTURELAYERTYPE_LITTEXTURE:
10026                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10027                         {
10028                                 // two-pass lit texture with 2x rgbscale
10029                                 // first the lightmap pass
10030                                 R_Mesh_TexBind(0, r_texture_white);
10031                                 R_Mesh_TexMatrix(0, NULL);
10032                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10033                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10034                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10035                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10036                                 else if (FAKELIGHT_ENABLED)
10037                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10038                                 else if (rsurface.uselightmaptexture)
10039                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10040                                 else
10041                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10042                                 // then apply the texture to it
10043                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10044                                 R_Mesh_TexBind(0, layer->texture);
10045                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10046                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10047                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10048                                 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
10049                         }
10050                         else
10051                         {
10052                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10053                                 R_Mesh_TexBind(0, layer->texture);
10054                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10055                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10056                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10057                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10058                                         RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10059                                 else if (FAKELIGHT_ENABLED)
10060                                         RSurf_DrawBatch_GL11_FakeLight(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10061                                 else
10062                                         RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10063                         }
10064                         break;
10065                 case TEXTURELAYERTYPE_TEXTURE:
10066                         // singletexture unlit texture with transparency support
10067                         R_Mesh_TexBind(0, layer->texture);
10068                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10069                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10070                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10071                         RSurf_DrawBatch_GL11_Unlit(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10072                         break;
10073                 case TEXTURELAYERTYPE_FOG:
10074                         // singletexture fogging
10075                         if (layer->texture)
10076                         {
10077                                 R_Mesh_TexBind(0, layer->texture);
10078                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10079                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10080                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10081                         }
10082                         else
10083                         {
10084                                 R_Mesh_TexBind(0, 0);
10085                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10086                         }
10087                         // generate a color array for the fog pass
10088                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10089                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10090                         RSurf_DrawBatch();
10091                         break;
10092                 default:
10093                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10094                 }
10095         }
10096         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10097         {
10098                 GL_DepthFunc(GL_LEQUAL);
10099                 GL_AlphaTest(false);
10100         }
10101 }
10102
10103 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10104 {
10105         int vi;
10106         int j;
10107         r_vertexgeneric_t *batchvertex;
10108         float c[4];
10109
10110 //      R_Mesh_ResetTextureState();
10111         R_SetupShader_Generic_NoTexture(false, false);
10112
10113         if(rsurface.texture && rsurface.texture->currentskinframe)
10114         {
10115                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10116                 c[3] *= rsurface.texture->currentalpha;
10117         }
10118         else
10119         {
10120                 c[0] = 1;
10121                 c[1] = 0;
10122                 c[2] = 1;
10123                 c[3] = 1;
10124         }
10125
10126         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10127         {
10128                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10129                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10130                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10131         }
10132
10133         // brighten it up (as texture value 127 means "unlit")
10134         c[0] *= 2 * r_refdef.view.colorscale;
10135         c[1] *= 2 * r_refdef.view.colorscale;
10136         c[2] *= 2 * r_refdef.view.colorscale;
10137
10138         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10139                 c[3] *= r_wateralpha.value;
10140
10141         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10142         {
10143                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10144                 GL_DepthMask(false);
10145         }
10146         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10147         {
10148                 GL_BlendFunc(GL_ONE, GL_ONE);
10149                 GL_DepthMask(false);
10150         }
10151         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10152         {
10153                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10154                 GL_DepthMask(false);
10155         }
10156         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10157         {
10158                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10159                 GL_DepthMask(false);
10160         }
10161         else
10162         {
10163                 GL_BlendFunc(GL_ONE, GL_ZERO);
10164                 GL_DepthMask(writedepth);
10165         }
10166
10167         if (r_showsurfaces.integer == 3)
10168         {
10169                 rsurface.passcolor4f = NULL;
10170
10171                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10172                 {
10173                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10174
10175                         rsurface.passcolor4f = NULL;
10176                         rsurface.passcolor4f_vertexbuffer = 0;
10177                         rsurface.passcolor4f_bufferoffset = 0;
10178                 }
10179                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10180                 {
10181                         qboolean applycolor = true;
10182                         float one = 1.0;
10183
10184                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10185
10186                         r_refdef.lightmapintensity = 1;
10187                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10188                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10189                 }
10190                 else if (FAKELIGHT_ENABLED)
10191                 {
10192                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10193
10194                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10195                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10196                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10197                 }
10198                 else
10199                 {
10200                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10201
10202                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10203                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10204                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10205                 }
10206
10207                 if(!rsurface.passcolor4f)
10208                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10209
10210                 RSurf_DrawBatch_GL11_ApplyAmbient();
10211                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10212                 if(r_refdef.fogenabled)
10213                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10214                 RSurf_DrawBatch_GL11_ClampColor();
10215
10216                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10217                 R_SetupShader_Generic_NoTexture(false, false);
10218                 RSurf_DrawBatch();
10219         }
10220         else if (!r_refdef.view.showdebug)
10221         {
10222                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10223                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10224                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10225                 {
10226                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10227                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10228                 }
10229                 R_Mesh_PrepareVertices_Generic_Unlock();
10230                 RSurf_DrawBatch();
10231         }
10232         else if (r_showsurfaces.integer == 4)
10233         {
10234                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10235                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10236                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10237                 {
10238                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10239                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10240                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10241                 }
10242                 R_Mesh_PrepareVertices_Generic_Unlock();
10243                 RSurf_DrawBatch();
10244         }
10245         else if (r_showsurfaces.integer == 2)
10246         {
10247                 const int *e;
10248                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10249                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10250                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10251                 {
10252                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10253                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10254                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10255                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10256                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10257                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10258                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10259                 }
10260                 R_Mesh_PrepareVertices_Generic_Unlock();
10261                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10262         }
10263         else
10264         {
10265                 int texturesurfaceindex;
10266                 int k;
10267                 const msurface_t *surface;
10268                 float surfacecolor4f[4];
10269                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10270                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10271                 vi = 0;
10272                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10273                 {
10274                         surface = texturesurfacelist[texturesurfaceindex];
10275                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10276                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10277                         for (j = 0;j < surface->num_vertices;j++)
10278                         {
10279                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10280                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10281                                 vi++;
10282                         }
10283                 }
10284                 R_Mesh_PrepareVertices_Generic_Unlock();
10285                 RSurf_DrawBatch();
10286         }
10287 }
10288
10289 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10290 {
10291         CHECKGLERROR
10292         RSurf_SetupDepthAndCulling();
10293         if (r_showsurfaces.integer)
10294         {
10295                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10296                 return;
10297         }
10298         switch (vid.renderpath)
10299         {
10300         case RENDERPATH_GL20:
10301         case RENDERPATH_D3D9:
10302         case RENDERPATH_D3D10:
10303         case RENDERPATH_D3D11:
10304         case RENDERPATH_SOFT:
10305         case RENDERPATH_GLES2:
10306                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10307                 break;
10308         case RENDERPATH_GL13:
10309         case RENDERPATH_GLES1:
10310                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10311                 break;
10312         case RENDERPATH_GL11:
10313                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10314                 break;
10315         }
10316         CHECKGLERROR
10317 }
10318
10319 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10320 {
10321         CHECKGLERROR
10322         RSurf_SetupDepthAndCulling();
10323         if (r_showsurfaces.integer)
10324         {
10325                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10326                 return;
10327         }
10328         switch (vid.renderpath)
10329         {
10330         case RENDERPATH_GL20:
10331         case RENDERPATH_D3D9:
10332         case RENDERPATH_D3D10:
10333         case RENDERPATH_D3D11:
10334         case RENDERPATH_SOFT:
10335         case RENDERPATH_GLES2:
10336                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10337                 break;
10338         case RENDERPATH_GL13:
10339         case RENDERPATH_GLES1:
10340                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10341                 break;
10342         case RENDERPATH_GL11:
10343                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10344                 break;
10345         }
10346         CHECKGLERROR
10347 }
10348
10349 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10350 {
10351         int i, j;
10352         int texturenumsurfaces, endsurface;
10353         texture_t *texture;
10354         const msurface_t *surface;
10355         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10356
10357         // if the model is static it doesn't matter what value we give for
10358         // wantnormals and wanttangents, so this logic uses only rules applicable
10359         // to a model, knowing that they are meaningless otherwise
10360         if (ent == r_refdef.scene.worldentity)
10361                 RSurf_ActiveWorldEntity();
10362         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10363                 RSurf_ActiveModelEntity(ent, false, false, false);
10364         else
10365         {
10366                 switch (vid.renderpath)
10367                 {
10368                 case RENDERPATH_GL20:
10369                 case RENDERPATH_D3D9:
10370                 case RENDERPATH_D3D10:
10371                 case RENDERPATH_D3D11:
10372                 case RENDERPATH_SOFT:
10373                 case RENDERPATH_GLES2:
10374                         RSurf_ActiveModelEntity(ent, true, true, false);
10375                         break;
10376                 case RENDERPATH_GL11:
10377                 case RENDERPATH_GL13:
10378                 case RENDERPATH_GLES1:
10379                         RSurf_ActiveModelEntity(ent, true, false, false);
10380                         break;
10381                 }
10382         }
10383
10384         if (r_transparentdepthmasking.integer)
10385         {
10386                 qboolean setup = false;
10387                 for (i = 0;i < numsurfaces;i = j)
10388                 {
10389                         j = i + 1;
10390                         surface = rsurface.modelsurfaces + surfacelist[i];
10391                         texture = surface->texture;
10392                         rsurface.texture = R_GetCurrentTexture(texture);
10393                         rsurface.lightmaptexture = NULL;
10394                         rsurface.deluxemaptexture = NULL;
10395                         rsurface.uselightmaptexture = false;
10396                         // scan ahead until we find a different texture
10397                         endsurface = min(i + 1024, numsurfaces);
10398                         texturenumsurfaces = 0;
10399                         texturesurfacelist[texturenumsurfaces++] = surface;
10400                         for (;j < endsurface;j++)
10401                         {
10402                                 surface = rsurface.modelsurfaces + surfacelist[j];
10403                                 if (texture != surface->texture)
10404                                         break;
10405                                 texturesurfacelist[texturenumsurfaces++] = surface;
10406                         }
10407                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10408                                 continue;
10409                         // render the range of surfaces as depth
10410                         if (!setup)
10411                         {
10412                                 setup = true;
10413                                 GL_ColorMask(0,0,0,0);
10414                                 GL_Color(1,1,1,1);
10415                                 GL_DepthTest(true);
10416                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10417                                 GL_DepthMask(true);
10418 //                              R_Mesh_ResetTextureState();
10419                                 R_SetupShader_DepthOrShadow(false, false);
10420                         }
10421                         RSurf_SetupDepthAndCulling();
10422                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10423                         if (rsurface.batchvertex3fbuffer)
10424                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10425                         else
10426                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10427                         RSurf_DrawBatch();
10428                 }
10429                 if (setup)
10430                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10431         }
10432
10433         for (i = 0;i < numsurfaces;i = j)
10434         {
10435                 j = i + 1;
10436                 surface = rsurface.modelsurfaces + surfacelist[i];
10437                 texture = surface->texture;
10438                 rsurface.texture = R_GetCurrentTexture(texture);
10439                 // scan ahead until we find a different texture
10440                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10441                 texturenumsurfaces = 0;
10442                 texturesurfacelist[texturenumsurfaces++] = surface;
10443                 if(FAKELIGHT_ENABLED)
10444                 {
10445                         rsurface.lightmaptexture = NULL;
10446                         rsurface.deluxemaptexture = NULL;
10447                         rsurface.uselightmaptexture = false;
10448                         for (;j < endsurface;j++)
10449                         {
10450                                 surface = rsurface.modelsurfaces + surfacelist[j];
10451                                 if (texture != surface->texture)
10452                                         break;
10453                                 texturesurfacelist[texturenumsurfaces++] = surface;
10454                         }
10455                 }
10456                 else
10457                 {
10458                         rsurface.lightmaptexture = surface->lightmaptexture;
10459                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10460                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10461                         for (;j < endsurface;j++)
10462                         {
10463                                 surface = rsurface.modelsurfaces + surfacelist[j];
10464                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10465                                         break;
10466                                 texturesurfacelist[texturenumsurfaces++] = surface;
10467                         }
10468                 }
10469                 // render the range of surfaces
10470                 if (ent == r_refdef.scene.worldentity)
10471                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10472                 else
10473                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10474         }
10475         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10476 }
10477
10478 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10479 {
10480         // transparent surfaces get pushed off into the transparent queue
10481         int surfacelistindex;
10482         const msurface_t *surface;
10483         vec3_t tempcenter, center;
10484         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10485         {
10486                 surface = texturesurfacelist[surfacelistindex];
10487                 if (r_transparent_sortsurfacesbynearest.integer)
10488                 {
10489                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10490                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10491                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10492                 }
10493                 else
10494                 {
10495                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10496                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10497                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10498                 }
10499                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10500                 if (rsurface.entity->transparent_offset) // transparent offset
10501                 {
10502                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10503                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10504                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10505                 }
10506                 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10507         }
10508 }
10509
10510 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10511 {
10512         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10513                 return;
10514         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10515                 return;
10516         RSurf_SetupDepthAndCulling();
10517         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10518         if (rsurface.batchvertex3fbuffer)
10519                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10520         else
10521                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10522         RSurf_DrawBatch();
10523 }
10524
10525 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10526 {
10527         CHECKGLERROR
10528         if (depthonly)
10529                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10530         else if (prepass)
10531         {
10532                 if (!rsurface.texture->currentnumlayers)
10533                         return;
10534                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10535                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10536                 else
10537                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10538         }
10539         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10540                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10541         else if (!rsurface.texture->currentnumlayers)
10542                 return;
10543         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10544         {
10545                 // in the deferred case, transparent surfaces were queued during prepass
10546                 if (!r_shadow_usingdeferredprepass)
10547                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10548         }
10549         else
10550         {
10551                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10552                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10553         }
10554         CHECKGLERROR
10555 }
10556
10557 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10558 {
10559         int i, j;
10560         texture_t *texture;
10561         R_FrameData_SetMark();
10562         // break the surface list down into batches by texture and use of lightmapping
10563         for (i = 0;i < numsurfaces;i = j)
10564         {
10565                 j = i + 1;
10566                 // texture is the base texture pointer, rsurface.texture is the
10567                 // current frame/skin the texture is directing us to use (for example
10568                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10569                 // use skin 1 instead)
10570                 texture = surfacelist[i]->texture;
10571                 rsurface.texture = R_GetCurrentTexture(texture);
10572                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10573                 {
10574                         // if this texture is not the kind we want, skip ahead to the next one
10575                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10576                                 ;
10577                         continue;
10578                 }
10579                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10580                 {
10581                         rsurface.lightmaptexture = NULL;
10582                         rsurface.deluxemaptexture = NULL;
10583                         rsurface.uselightmaptexture = false;
10584                         // simply scan ahead until we find a different texture or lightmap state
10585                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10586                                 ;
10587                 }
10588                 else
10589                 {
10590                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10591                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10592                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10593                         // simply scan ahead until we find a different texture or lightmap state
10594                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10595                                 ;
10596                 }
10597                 // render the range of surfaces
10598                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10599         }
10600         R_FrameData_ReturnToMark();
10601 }
10602
10603 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10604 {
10605         CHECKGLERROR
10606         if (depthonly)
10607                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10608         else if (prepass)
10609         {
10610                 if (!rsurface.texture->currentnumlayers)
10611                         return;
10612                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10613                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10614                 else
10615                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10616         }
10617         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10618                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10619         else if (!rsurface.texture->currentnumlayers)
10620                 return;
10621         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10622         {
10623                 // in the deferred case, transparent surfaces were queued during prepass
10624                 if (!r_shadow_usingdeferredprepass)
10625                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10626         }
10627         else
10628         {
10629                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10630                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10631         }
10632         CHECKGLERROR
10633 }
10634
10635 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10636 {
10637         int i, j;
10638         texture_t *texture;
10639         R_FrameData_SetMark();
10640         // break the surface list down into batches by texture and use of lightmapping
10641         for (i = 0;i < numsurfaces;i = j)
10642         {
10643                 j = i + 1;
10644                 // texture is the base texture pointer, rsurface.texture is the
10645                 // current frame/skin the texture is directing us to use (for example
10646                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10647                 // use skin 1 instead)
10648                 texture = surfacelist[i]->texture;
10649                 rsurface.texture = R_GetCurrentTexture(texture);
10650                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10651                 {
10652                         // if this texture is not the kind we want, skip ahead to the next one
10653                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10654                                 ;
10655                         continue;
10656                 }
10657                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10658                 {
10659                         rsurface.lightmaptexture = NULL;
10660                         rsurface.deluxemaptexture = NULL;
10661                         rsurface.uselightmaptexture = false;
10662                         // simply scan ahead until we find a different texture or lightmap state
10663                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10664                                 ;
10665                 }
10666                 else
10667                 {
10668                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10669                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10670                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10671                         // simply scan ahead until we find a different texture or lightmap state
10672                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10673                                 ;
10674                 }
10675                 // render the range of surfaces
10676                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10677         }
10678         R_FrameData_ReturnToMark();
10679 }
10680
10681 float locboxvertex3f[6*4*3] =
10682 {
10683         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10684         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10685         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10686         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10687         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10688         1,0,0, 0,0,0, 0,1,0, 1,1,0
10689 };
10690
10691 unsigned short locboxelements[6*2*3] =
10692 {
10693          0, 1, 2, 0, 2, 3,
10694          4, 5, 6, 4, 6, 7,
10695          8, 9,10, 8,10,11,
10696         12,13,14, 12,14,15,
10697         16,17,18, 16,18,19,
10698         20,21,22, 20,22,23
10699 };
10700
10701 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10702 {
10703         int i, j;
10704         cl_locnode_t *loc = (cl_locnode_t *)ent;
10705         vec3_t mins, size;
10706         float vertex3f[6*4*3];
10707         CHECKGLERROR
10708         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10709         GL_DepthMask(false);
10710         GL_DepthRange(0, 1);
10711         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10712         GL_DepthTest(true);
10713         GL_CullFace(GL_NONE);
10714         R_EntityMatrix(&identitymatrix);
10715
10716 //      R_Mesh_ResetTextureState();
10717
10718         i = surfacelist[0];
10719         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10720                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10721                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10722                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10723
10724         if (VectorCompare(loc->mins, loc->maxs))
10725         {
10726                 VectorSet(size, 2, 2, 2);
10727                 VectorMA(loc->mins, -0.5f, size, mins);
10728         }
10729         else
10730         {
10731                 VectorCopy(loc->mins, mins);
10732                 VectorSubtract(loc->maxs, loc->mins, size);
10733         }
10734
10735         for (i = 0;i < 6*4*3;)
10736                 for (j = 0;j < 3;j++, i++)
10737                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10738
10739         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10740         R_SetupShader_Generic_NoTexture(false, false);
10741         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10742 }
10743
10744 void R_DrawLocs(void)
10745 {
10746         int index;
10747         cl_locnode_t *loc, *nearestloc;
10748         vec3_t center;
10749         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10750         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10751         {
10752                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10753                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10754         }
10755 }
10756
10757 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10758 {
10759         if (decalsystem->decals)
10760                 Mem_Free(decalsystem->decals);
10761         memset(decalsystem, 0, sizeof(*decalsystem));
10762 }
10763
10764 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
10765 {
10766         tridecal_t *decal;
10767         tridecal_t *decals;
10768         int i;
10769
10770         // expand or initialize the system
10771         if (decalsystem->maxdecals <= decalsystem->numdecals)
10772         {
10773                 decalsystem_t old = *decalsystem;
10774                 qboolean useshortelements;
10775                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10776                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10777                 decalsystem->decals = (tridecal_t *)Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
10778                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10779                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10780                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10781                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10782                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10783                 if (decalsystem->numdecals)
10784                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10785                 if (old.decals)
10786                         Mem_Free(old.decals);
10787                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10788                         decalsystem->element3i[i] = i;
10789                 if (useshortelements)
10790                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10791                                 decalsystem->element3s[i] = i;
10792         }
10793
10794         // grab a decal and search for another free slot for the next one
10795         decals = decalsystem->decals;
10796         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10797         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10798                 ;
10799         decalsystem->freedecal = i;
10800         if (decalsystem->numdecals <= i)
10801                 decalsystem->numdecals = i + 1;
10802
10803         // initialize the decal
10804         decal->lived = 0;
10805         decal->triangleindex = triangleindex;
10806         decal->surfaceindex = surfaceindex;
10807         decal->decalsequence = decalsequence;
10808         decal->color4f[0][0] = c0[0];
10809         decal->color4f[0][1] = c0[1];
10810         decal->color4f[0][2] = c0[2];
10811         decal->color4f[0][3] = 1;
10812         decal->color4f[1][0] = c1[0];
10813         decal->color4f[1][1] = c1[1];
10814         decal->color4f[1][2] = c1[2];
10815         decal->color4f[1][3] = 1;
10816         decal->color4f[2][0] = c2[0];
10817         decal->color4f[2][1] = c2[1];
10818         decal->color4f[2][2] = c2[2];
10819         decal->color4f[2][3] = 1;
10820         decal->vertex3f[0][0] = v0[0];
10821         decal->vertex3f[0][1] = v0[1];
10822         decal->vertex3f[0][2] = v0[2];
10823         decal->vertex3f[1][0] = v1[0];
10824         decal->vertex3f[1][1] = v1[1];
10825         decal->vertex3f[1][2] = v1[2];
10826         decal->vertex3f[2][0] = v2[0];
10827         decal->vertex3f[2][1] = v2[1];
10828         decal->vertex3f[2][2] = v2[2];
10829         decal->texcoord2f[0][0] = t0[0];
10830         decal->texcoord2f[0][1] = t0[1];
10831         decal->texcoord2f[1][0] = t1[0];
10832         decal->texcoord2f[1][1] = t1[1];
10833         decal->texcoord2f[2][0] = t2[0];
10834         decal->texcoord2f[2][1] = t2[1];
10835         TriangleNormal(v0, v1, v2, decal->plane);
10836         VectorNormalize(decal->plane);
10837         decal->plane[3] = DotProduct(v0, decal->plane);
10838 }
10839
10840 extern cvar_t cl_decals_bias;
10841 extern cvar_t cl_decals_models;
10842 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10843 // baseparms, parms, temps
10844 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
10845 {
10846         int cornerindex;
10847         int index;
10848         float v[9][3];
10849         const float *vertex3f;
10850         const float *normal3f;
10851         int numpoints;
10852         float points[2][9][3];
10853         float temp[3];
10854         float tc[9][2];
10855         float f;
10856         float c[9][4];
10857         const int *e;
10858
10859         e = rsurface.modelelement3i + 3*triangleindex;
10860
10861         vertex3f = rsurface.modelvertex3f;
10862         normal3f = rsurface.modelnormal3f;
10863
10864         if (normal3f)
10865         {
10866                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10867                 {
10868                         index = 3*e[cornerindex];
10869                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10870                 }
10871         }
10872         else
10873         {
10874                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10875                 {
10876                         index = 3*e[cornerindex];
10877                         VectorCopy(vertex3f + index, v[cornerindex]);
10878                 }
10879         }
10880
10881         // cull backfaces
10882         //TriangleNormal(v[0], v[1], v[2], normal);
10883         //if (DotProduct(normal, localnormal) < 0.0f)
10884         //      continue;
10885         // clip by each of the box planes formed from the projection matrix
10886         // if anything survives, we emit the decal
10887         numpoints = PolygonF_Clip(3        , v[0]        , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10888         if (numpoints < 3)
10889                 return;
10890         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10891         if (numpoints < 3)
10892                 return;
10893         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10894         if (numpoints < 3)
10895                 return;
10896         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10897         if (numpoints < 3)
10898                 return;
10899         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10900         if (numpoints < 3)
10901                 return;
10902         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
10903         if (numpoints < 3)
10904                 return;
10905         // some part of the triangle survived, so we have to accept it...
10906         if (dynamic)
10907         {
10908                 // dynamic always uses the original triangle
10909                 numpoints = 3;
10910                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10911                 {
10912                         index = 3*e[cornerindex];
10913                         VectorCopy(vertex3f + index, v[cornerindex]);
10914                 }
10915         }
10916         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10917         {
10918                 // convert vertex positions to texcoords
10919                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10920                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10921                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10922                 // calculate distance fade from the projection origin
10923                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10924                 f = bound(0.0f, f, 1.0f);
10925                 c[cornerindex][0] = r * f;
10926                 c[cornerindex][1] = g * f;
10927                 c[cornerindex][2] = b * f;
10928                 c[cornerindex][3] = 1.0f;
10929                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10930         }
10931         if (dynamic)
10932                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
10933         else
10934                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10935                         R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
10936 }
10937 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10938 {
10939         matrix4x4_t projection;
10940         decalsystem_t *decalsystem;
10941         qboolean dynamic;
10942         dp_model_t *model;
10943         const msurface_t *surface;
10944         const msurface_t *surfaces;
10945         const int *surfacelist;
10946         const texture_t *texture;
10947         int numtriangles;
10948         int numsurfacelist;
10949         int surfacelistindex;
10950         int surfaceindex;
10951         int triangleindex;
10952         float localorigin[3];
10953         float localnormal[3];
10954         float localmins[3];
10955         float localmaxs[3];
10956         float localsize;
10957         //float normal[3];
10958         float planes[6][4];
10959         float angles[3];
10960         bih_t *bih;
10961         int bih_triangles_count;
10962         int bih_triangles[256];
10963         int bih_surfaces[256];
10964
10965         decalsystem = &ent->decalsystem;
10966         model = ent->model;
10967         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10968         {
10969                 R_DecalSystem_Reset(&ent->decalsystem);
10970                 return;
10971         }
10972
10973         if (!model->brush.data_leafs && !cl_decals_models.integer)
10974         {
10975                 if (decalsystem->model)
10976                         R_DecalSystem_Reset(decalsystem);
10977                 return;
10978         }
10979
10980         if (decalsystem->model != model)
10981                 R_DecalSystem_Reset(decalsystem);
10982         decalsystem->model = model;
10983
10984         RSurf_ActiveModelEntity(ent, true, false, false);
10985
10986         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10987         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10988         VectorNormalize(localnormal);
10989         localsize = worldsize*rsurface.inversematrixscale;
10990         localmins[0] = localorigin[0] - localsize;
10991         localmins[1] = localorigin[1] - localsize;
10992         localmins[2] = localorigin[2] - localsize;
10993         localmaxs[0] = localorigin[0] + localsize;
10994         localmaxs[1] = localorigin[1] + localsize;
10995         localmaxs[2] = localorigin[2] + localsize;
10996
10997         //VectorCopy(localnormal, planes[4]);
10998         //VectorVectors(planes[4], planes[2], planes[0]);
10999         AnglesFromVectors(angles, localnormal, NULL, false);
11000         AngleVectors(angles, planes[0], planes[2], planes[4]);
11001         VectorNegate(planes[0], planes[1]);
11002         VectorNegate(planes[2], planes[3]);
11003         VectorNegate(planes[4], planes[5]);
11004         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11005         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11006         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11007         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11008         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11009         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11010
11011 #if 1
11012 // works
11013 {
11014         matrix4x4_t forwardprojection;
11015         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11016         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11017 }
11018 #else
11019 // broken
11020 {
11021         float projectionvector[4][3];
11022         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11023         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11024         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11025         projectionvector[0][0] = planes[0][0] * ilocalsize;
11026         projectionvector[0][1] = planes[1][0] * ilocalsize;
11027         projectionvector[0][2] = planes[2][0] * ilocalsize;
11028         projectionvector[1][0] = planes[0][1] * ilocalsize;
11029         projectionvector[1][1] = planes[1][1] * ilocalsize;
11030         projectionvector[1][2] = planes[2][1] * ilocalsize;
11031         projectionvector[2][0] = planes[0][2] * ilocalsize;
11032         projectionvector[2][1] = planes[1][2] * ilocalsize;
11033         projectionvector[2][2] = planes[2][2] * ilocalsize;
11034         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11035         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11036         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11037         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11038 }
11039 #endif
11040
11041         dynamic = model->surfmesh.isanimated;
11042         numsurfacelist = model->nummodelsurfaces;
11043         surfacelist = model->sortedmodelsurfaces;
11044         surfaces = model->data_surfaces;
11045
11046         bih = NULL;
11047         bih_triangles_count = -1;
11048         if(!dynamic)
11049         {
11050                 if(model->render_bih.numleafs)
11051                         bih = &model->render_bih;
11052                 else if(model->collision_bih.numleafs)
11053                         bih = &model->collision_bih;
11054         }
11055         if(bih)
11056                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11057         if(bih_triangles_count == 0)
11058                 return;
11059         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11060                 return;
11061         if(bih_triangles_count > 0)
11062         {
11063                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11064                 {
11065                         surfaceindex = bih_surfaces[triangleindex];
11066                         surface = surfaces + surfaceindex;
11067                         texture = surface->texture;
11068                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11069                                 continue;
11070                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11071                                 continue;
11072                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11073                 }
11074         }
11075         else
11076         {
11077                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11078                 {
11079                         surfaceindex = surfacelist[surfacelistindex];
11080                         surface = surfaces + surfaceindex;
11081                         // check cull box first because it rejects more than any other check
11082                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11083                                 continue;
11084                         // skip transparent surfaces
11085                         texture = surface->texture;
11086                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11087                                 continue;
11088                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11089                                 continue;
11090                         numtriangles = surface->num_triangles;
11091                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11092                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11093                 }
11094         }
11095 }
11096
11097 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11098 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11099 {
11100         int renderentityindex;
11101         float worldmins[3];
11102         float worldmaxs[3];
11103         entity_render_t *ent;
11104
11105         if (!cl_decals_newsystem.integer)
11106                 return;
11107
11108         worldmins[0] = worldorigin[0] - worldsize;
11109         worldmins[1] = worldorigin[1] - worldsize;
11110         worldmins[2] = worldorigin[2] - worldsize;
11111         worldmaxs[0] = worldorigin[0] + worldsize;
11112         worldmaxs[1] = worldorigin[1] + worldsize;
11113         worldmaxs[2] = worldorigin[2] + worldsize;
11114
11115         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11116
11117         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11118         {
11119                 ent = r_refdef.scene.entities[renderentityindex];
11120                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11121                         continue;
11122
11123                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11124         }
11125 }
11126
11127 typedef struct r_decalsystem_splatqueue_s
11128 {
11129         vec3_t worldorigin;
11130         vec3_t worldnormal;
11131         float color[4];
11132         float tcrange[4];
11133         float worldsize;
11134         int decalsequence;
11135 }
11136 r_decalsystem_splatqueue_t;
11137
11138 int r_decalsystem_numqueued = 0;
11139 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11140
11141 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
11142 {
11143         r_decalsystem_splatqueue_t *queue;
11144
11145         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11146                 return;
11147
11148         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11149         VectorCopy(worldorigin, queue->worldorigin);
11150         VectorCopy(worldnormal, queue->worldnormal);
11151         Vector4Set(queue->color, r, g, b, a);
11152         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11153         queue->worldsize = worldsize;
11154         queue->decalsequence = cl.decalsequence++;
11155 }
11156
11157 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11158 {
11159         int i;
11160         r_decalsystem_splatqueue_t *queue;
11161
11162         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11163                 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
11164         r_decalsystem_numqueued = 0;
11165 }
11166
11167 extern cvar_t cl_decals_max;
11168 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11169 {
11170         int i;
11171         decalsystem_t *decalsystem = &ent->decalsystem;
11172         int numdecals;
11173         int killsequence;
11174         tridecal_t *decal;
11175         float frametime;
11176         float lifetime;
11177
11178         if (!decalsystem->numdecals)
11179                 return;
11180
11181         if (r_showsurfaces.integer)
11182                 return;
11183
11184         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11185         {
11186                 R_DecalSystem_Reset(decalsystem);
11187                 return;
11188         }
11189
11190         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11191         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11192
11193         if (decalsystem->lastupdatetime)
11194                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11195         else
11196                 frametime = 0;
11197         decalsystem->lastupdatetime = r_refdef.scene.time;
11198         numdecals = decalsystem->numdecals;
11199
11200         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11201         {
11202                 if (decal->color4f[0][3])
11203                 {
11204                         decal->lived += frametime;
11205                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11206                         {
11207                                 memset(decal, 0, sizeof(*decal));
11208                                 if (decalsystem->freedecal > i)
11209                                         decalsystem->freedecal = i;
11210                         }
11211                 }
11212         }
11213         decal = decalsystem->decals;
11214         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11215                 numdecals--;
11216
11217         // collapse the array by shuffling the tail decals into the gaps
11218         for (;;)
11219         {
11220                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11221                         decalsystem->freedecal++;
11222                 if (decalsystem->freedecal == numdecals)
11223                         break;
11224                 decal[decalsystem->freedecal] = decal[--numdecals];
11225         }
11226
11227         decalsystem->numdecals = numdecals;
11228
11229         if (numdecals <= 0)
11230         {
11231                 // if there are no decals left, reset decalsystem
11232                 R_DecalSystem_Reset(decalsystem);
11233         }
11234 }
11235
11236 extern skinframe_t *decalskinframe;
11237 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11238 {
11239         int i;
11240         decalsystem_t *decalsystem = &ent->decalsystem;
11241         int numdecals;
11242         tridecal_t *decal;
11243         float faderate;
11244         float alpha;
11245         float *v3f;
11246         float *c4f;
11247         float *t2f;
11248         const int *e;
11249         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11250         int numtris = 0;
11251
11252         numdecals = decalsystem->numdecals;
11253         if (!numdecals)
11254                 return;
11255
11256         if (r_showsurfaces.integer)
11257                 return;
11258
11259         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11260         {
11261                 R_DecalSystem_Reset(decalsystem);
11262                 return;
11263         }
11264
11265         // if the model is static it doesn't matter what value we give for
11266         // wantnormals and wanttangents, so this logic uses only rules applicable
11267         // to a model, knowing that they are meaningless otherwise
11268         if (ent == r_refdef.scene.worldentity)
11269                 RSurf_ActiveWorldEntity();
11270         else
11271                 RSurf_ActiveModelEntity(ent, false, false, false);
11272
11273         decalsystem->lastupdatetime = r_refdef.scene.time;
11274
11275         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11276
11277         // update vertex positions for animated models
11278         v3f = decalsystem->vertex3f;
11279         c4f = decalsystem->color4f;
11280         t2f = decalsystem->texcoord2f;
11281         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11282         {
11283                 if (!decal->color4f[0][3])
11284                         continue;
11285
11286                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11287                         continue;
11288
11289                 // skip backfaces
11290                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11291                         continue;
11292
11293                 // update color values for fading decals
11294                 if (decal->lived >= cl_decals_time.value)
11295                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11296                 else
11297                         alpha = 1.0f;
11298
11299                 c4f[ 0] = decal->color4f[0][0] * alpha;
11300                 c4f[ 1] = decal->color4f[0][1] * alpha;
11301                 c4f[ 2] = decal->color4f[0][2] * alpha;
11302                 c4f[ 3] = 1;
11303                 c4f[ 4] = decal->color4f[1][0] * alpha;
11304                 c4f[ 5] = decal->color4f[1][1] * alpha;
11305                 c4f[ 6] = decal->color4f[1][2] * alpha;
11306                 c4f[ 7] = 1;
11307                 c4f[ 8] = decal->color4f[2][0] * alpha;
11308                 c4f[ 9] = decal->color4f[2][1] * alpha;
11309                 c4f[10] = decal->color4f[2][2] * alpha;
11310                 c4f[11] = 1;
11311
11312                 t2f[0] = decal->texcoord2f[0][0];
11313                 t2f[1] = decal->texcoord2f[0][1];
11314                 t2f[2] = decal->texcoord2f[1][0];
11315                 t2f[3] = decal->texcoord2f[1][1];
11316                 t2f[4] = decal->texcoord2f[2][0];
11317                 t2f[5] = decal->texcoord2f[2][1];
11318
11319                 // update vertex positions for animated models
11320                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11321                 {
11322                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11323                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11324                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11325                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11326                 }
11327                 else
11328                 {
11329                         VectorCopy(decal->vertex3f[0], v3f);
11330                         VectorCopy(decal->vertex3f[1], v3f + 3);
11331                         VectorCopy(decal->vertex3f[2], v3f + 6);
11332                 }
11333
11334                 if (r_refdef.fogenabled)
11335                 {
11336                         alpha = RSurf_FogVertex(v3f);
11337                         VectorScale(c4f, alpha, c4f);
11338                         alpha = RSurf_FogVertex(v3f + 3);
11339                         VectorScale(c4f + 4, alpha, c4f + 4);
11340                         alpha = RSurf_FogVertex(v3f + 6);
11341                         VectorScale(c4f + 8, alpha, c4f + 8);
11342                 }
11343
11344                 v3f += 9;
11345                 c4f += 12;
11346                 t2f += 6;
11347                 numtris++;
11348         }
11349
11350         if (numtris > 0)
11351         {
11352                 r_refdef.stats.drawndecals += numtris;
11353
11354                 // now render the decals all at once
11355                 // (this assumes they all use one particle font texture!)
11356                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11357 //              R_Mesh_ResetTextureState();
11358                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11359                 GL_DepthMask(false);
11360                 GL_DepthRange(0, 1);
11361                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11362                 GL_DepthTest(true);
11363                 GL_CullFace(GL_NONE);
11364                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11365                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11366                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11367         }
11368 }
11369
11370 static void R_DrawModelDecals(void)
11371 {
11372         int i, numdecals;
11373
11374         // fade faster when there are too many decals
11375         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11376         for (i = 0;i < r_refdef.scene.numentities;i++)
11377                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11378
11379         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11380         for (i = 0;i < r_refdef.scene.numentities;i++)
11381                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11382                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11383
11384         R_DecalSystem_ApplySplatEntitiesQueue();
11385
11386         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11387         for (i = 0;i < r_refdef.scene.numentities;i++)
11388                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11389
11390         r_refdef.stats.totaldecals += numdecals;
11391
11392         if (r_showsurfaces.integer)
11393                 return;
11394
11395         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11396
11397         for (i = 0;i < r_refdef.scene.numentities;i++)
11398         {
11399                 if (!r_refdef.viewcache.entityvisible[i])
11400                         continue;
11401                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11402                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11403         }
11404 }
11405
11406 extern cvar_t mod_collision_bih;
11407 static void R_DrawDebugModel(void)
11408 {
11409         entity_render_t *ent = rsurface.entity;
11410         int i, j, k, l, flagsmask;
11411         const msurface_t *surface;
11412         dp_model_t *model = ent->model;
11413         vec3_t v;
11414
11415         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11416                 return;
11417
11418         if (r_showoverdraw.value > 0)
11419         {
11420                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11421                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11422                 R_SetupShader_Generic_NoTexture(false, false);
11423                 GL_DepthTest(false);
11424                 GL_DepthMask(false);
11425                 GL_DepthRange(0, 1);
11426                 GL_BlendFunc(GL_ONE, GL_ONE);
11427                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11428                 {
11429                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11430                                 continue;
11431                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11432                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11433                         {
11434                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11435                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11436                                 if (!rsurface.texture->currentlayers->depthmask)
11437                                         GL_Color(c, 0, 0, 1.0f);
11438                                 else if (ent == r_refdef.scene.worldentity)
11439                                         GL_Color(c, c, c, 1.0f);
11440                                 else
11441                                         GL_Color(0, c, 0, 1.0f);
11442                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11443                                 RSurf_DrawBatch();
11444                         }
11445                 }
11446                 rsurface.texture = NULL;
11447         }
11448
11449         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11450
11451 //      R_Mesh_ResetTextureState();
11452         R_SetupShader_Generic_NoTexture(false, false);
11453         GL_DepthRange(0, 1);
11454         GL_DepthTest(!r_showdisabledepthtest.integer);
11455         GL_DepthMask(false);
11456         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11457
11458         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11459         {
11460                 int triangleindex;
11461                 int bihleafindex;
11462                 qboolean cullbox = false;
11463                 const q3mbrush_t *brush;
11464                 const bih_t *bih = &model->collision_bih;
11465                 const bih_leaf_t *bihleaf;
11466                 float vertex3f[3][3];
11467                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11468                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11469                 {
11470                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11471                                 continue;
11472                         switch (bihleaf->type)
11473                         {
11474                         case BIH_BRUSH:
11475                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11476                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11477                                 {
11478                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11479                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11480                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11481                                 }
11482                                 break;
11483                         case BIH_COLLISIONTRIANGLE:
11484                                 triangleindex = bihleaf->itemindex;
11485                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11486                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11487                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11488                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11489                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11490                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11491                                 break;
11492                         case BIH_RENDERTRIANGLE:
11493                                 triangleindex = bihleaf->itemindex;
11494                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11495                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11496                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11497                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11498                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11499                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11500                                 break;
11501                         }
11502                 }
11503         }
11504
11505         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11506
11507 #ifndef USE_GLES2
11508         if (r_showtris.integer && qglPolygonMode)
11509         {
11510                 if (r_showdisabledepthtest.integer)
11511                 {
11512                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11513                         GL_DepthMask(false);
11514                 }
11515                 else
11516                 {
11517                         GL_BlendFunc(GL_ONE, GL_ZERO);
11518                         GL_DepthMask(true);
11519                 }
11520                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11521                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11522                 {
11523                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11524                                 continue;
11525                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11526                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11527                         {
11528                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11529                                 if (!rsurface.texture->currentlayers->depthmask)
11530                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11531                                 else if (ent == r_refdef.scene.worldentity)
11532                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11533                                 else
11534                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11535                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11536                                 RSurf_DrawBatch();
11537                         }
11538                 }
11539                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11540                 rsurface.texture = NULL;
11541         }
11542
11543         if (r_shownormals.value != 0 && qglBegin)
11544         {
11545                 if (r_showdisabledepthtest.integer)
11546                 {
11547                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11548                         GL_DepthMask(false);
11549                 }
11550                 else
11551                 {
11552                         GL_BlendFunc(GL_ONE, GL_ZERO);
11553                         GL_DepthMask(true);
11554                 }
11555                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11556                 {
11557                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11558                                 continue;
11559                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11560                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11561                         {
11562                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11563                                 qglBegin(GL_LINES);
11564                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11565                                 {
11566                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11567                                         {
11568                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11569                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11570                                                 qglVertex3f(v[0], v[1], v[2]);
11571                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11572                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11573                                                 qglVertex3f(v[0], v[1], v[2]);
11574                                         }
11575                                 }
11576                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11577                                 {
11578                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11579                                         {
11580                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11581                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11582                                                 qglVertex3f(v[0], v[1], v[2]);
11583                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11584                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11585                                                 qglVertex3f(v[0], v[1], v[2]);
11586                                         }
11587                                 }
11588                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11589                                 {
11590                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11591                                         {
11592                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11593                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11594                                                 qglVertex3f(v[0], v[1], v[2]);
11595                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11596                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11597                                                 qglVertex3f(v[0], v[1], v[2]);
11598                                         }
11599                                 }
11600                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11601                                 {
11602                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11603                                         {
11604                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11605                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11606                                                 qglVertex3f(v[0], v[1], v[2]);
11607                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11608                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11609                                                 qglVertex3f(v[0], v[1], v[2]);
11610                                         }
11611                                 }
11612                                 qglEnd();
11613                                 CHECKGLERROR
11614                         }
11615                 }
11616                 rsurface.texture = NULL;
11617         }
11618 #endif
11619 }
11620
11621 int r_maxsurfacelist = 0;
11622 const msurface_t **r_surfacelist = NULL;
11623 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11624 {
11625         int i, j, endj, flagsmask;
11626         dp_model_t *model = r_refdef.scene.worldmodel;
11627         msurface_t *surfaces;
11628         unsigned char *update;
11629         int numsurfacelist = 0;
11630         if (model == NULL)
11631                 return;
11632
11633         if (r_maxsurfacelist < model->num_surfaces)
11634         {
11635                 r_maxsurfacelist = model->num_surfaces;
11636                 if (r_surfacelist)
11637                         Mem_Free((msurface_t**)r_surfacelist);
11638                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11639         }
11640
11641         RSurf_ActiveWorldEntity();
11642
11643         surfaces = model->data_surfaces;
11644         update = model->brushq1.lightmapupdateflags;
11645
11646         // update light styles on this submodel
11647         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11648         {
11649                 model_brush_lightstyleinfo_t *style;
11650                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11651                 {
11652                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11653                         {
11654                                 int *list = style->surfacelist;
11655                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11656                                 for (j = 0;j < style->numsurfaces;j++)
11657                                         update[list[j]] = true;
11658                         }
11659                 }
11660         }
11661
11662         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11663
11664         if (debug)
11665         {
11666                 R_DrawDebugModel();
11667                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11668                 return;
11669         }
11670
11671         rsurface.lightmaptexture = NULL;
11672         rsurface.deluxemaptexture = NULL;
11673         rsurface.uselightmaptexture = false;
11674         rsurface.texture = NULL;
11675         rsurface.rtlight = NULL;
11676         numsurfacelist = 0;
11677         // add visible surfaces to draw list
11678         for (i = 0;i < model->nummodelsurfaces;i++)
11679         {
11680                 j = model->sortedmodelsurfaces[i];
11681                 if (r_refdef.viewcache.world_surfacevisible[j])
11682                         r_surfacelist[numsurfacelist++] = surfaces + j;
11683         }
11684         // update lightmaps if needed
11685         if (model->brushq1.firstrender)
11686         {
11687                 model->brushq1.firstrender = false;
11688                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11689                         if (update[j])
11690                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11691         }
11692         else if (update)
11693         {
11694                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11695                         if (r_refdef.viewcache.world_surfacevisible[j])
11696                                 if (update[j])
11697                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11698         }
11699         // don't do anything if there were no surfaces
11700         if (!numsurfacelist)
11701         {
11702                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11703                 return;
11704         }
11705         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11706
11707         // add to stats if desired
11708         if (r_speeds.integer && !skysurfaces && !depthonly)
11709         {
11710                 r_refdef.stats.world_surfaces += numsurfacelist;
11711                 for (j = 0;j < numsurfacelist;j++)
11712                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11713         }
11714
11715         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11716 }
11717
11718 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11719 {
11720         int i, j, endj, flagsmask;
11721         dp_model_t *model = ent->model;
11722         msurface_t *surfaces;
11723         unsigned char *update;
11724         int numsurfacelist = 0;
11725         if (model == NULL)
11726                 return;
11727
11728         if (r_maxsurfacelist < model->num_surfaces)
11729         {
11730                 r_maxsurfacelist = model->num_surfaces;
11731                 if (r_surfacelist)
11732                         Mem_Free((msurface_t **)r_surfacelist);
11733                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11734         }
11735
11736         // if the model is static it doesn't matter what value we give for
11737         // wantnormals and wanttangents, so this logic uses only rules applicable
11738         // to a model, knowing that they are meaningless otherwise
11739         if (ent == r_refdef.scene.worldentity)
11740                 RSurf_ActiveWorldEntity();
11741         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11742                 RSurf_ActiveModelEntity(ent, false, false, false);
11743         else if (prepass)
11744                 RSurf_ActiveModelEntity(ent, true, true, true);
11745         else if (depthonly)
11746         {
11747                 switch (vid.renderpath)
11748                 {
11749                 case RENDERPATH_GL20:
11750                 case RENDERPATH_D3D9:
11751                 case RENDERPATH_D3D10:
11752                 case RENDERPATH_D3D11:
11753                 case RENDERPATH_SOFT:
11754                 case RENDERPATH_GLES2:
11755                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11756                         break;
11757                 case RENDERPATH_GL11:
11758                 case RENDERPATH_GL13:
11759                 case RENDERPATH_GLES1:
11760                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11761                         break;
11762                 }
11763         }
11764         else
11765         {
11766                 switch (vid.renderpath)
11767                 {
11768                 case RENDERPATH_GL20:
11769                 case RENDERPATH_D3D9:
11770                 case RENDERPATH_D3D10:
11771                 case RENDERPATH_D3D11:
11772                 case RENDERPATH_SOFT:
11773                 case RENDERPATH_GLES2:
11774                         RSurf_ActiveModelEntity(ent, true, true, false);
11775                         break;
11776                 case RENDERPATH_GL11:
11777                 case RENDERPATH_GL13:
11778                 case RENDERPATH_GLES1:
11779                         RSurf_ActiveModelEntity(ent, true, false, false);
11780                         break;
11781                 }
11782         }
11783
11784         surfaces = model->data_surfaces;
11785         update = model->brushq1.lightmapupdateflags;
11786
11787         // update light styles
11788         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11789         {
11790                 model_brush_lightstyleinfo_t *style;
11791                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11792                 {
11793                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11794                         {
11795                                 int *list = style->surfacelist;
11796                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11797                                 for (j = 0;j < style->numsurfaces;j++)
11798                                         update[list[j]] = true;
11799                         }
11800                 }
11801         }
11802
11803         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11804
11805         if (debug)
11806         {
11807                 R_DrawDebugModel();
11808                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11809                 return;
11810         }
11811
11812         rsurface.lightmaptexture = NULL;
11813         rsurface.deluxemaptexture = NULL;
11814         rsurface.uselightmaptexture = false;
11815         rsurface.texture = NULL;
11816         rsurface.rtlight = NULL;
11817         numsurfacelist = 0;
11818         // add visible surfaces to draw list
11819         for (i = 0;i < model->nummodelsurfaces;i++)
11820                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11821         // don't do anything if there were no surfaces
11822         if (!numsurfacelist)
11823         {
11824                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11825                 return;
11826         }
11827         // update lightmaps if needed
11828         if (update)
11829         {
11830                 int updated = 0;
11831                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11832                 {
11833                         if (update[j])
11834                         {
11835                                 updated++;
11836                                 R_BuildLightMap(ent, surfaces + j);
11837                         }
11838                 }
11839         }
11840
11841         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11842
11843         // add to stats if desired
11844         if (r_speeds.integer && !skysurfaces && !depthonly)
11845         {
11846                 r_refdef.stats.entities_surfaces += numsurfacelist;
11847                 for (j = 0;j < numsurfacelist;j++)
11848                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11849         }
11850
11851         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11852 }
11853
11854 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11855 {
11856         static texture_t texture;
11857         static msurface_t surface;
11858         const msurface_t *surfacelist = &surface;
11859
11860         // fake enough texture and surface state to render this geometry
11861
11862         texture.update_lastrenderframe = -1; // regenerate this texture
11863         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11864         texture.currentskinframe = skinframe;
11865         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11866         texture.offsetmapping = OFFSETMAPPING_OFF;
11867         texture.offsetscale = 1;
11868         texture.specularscalemod = 1;
11869         texture.specularpowermod = 1;
11870         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
11871         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
11872         // JUST GREP FOR "specularscalemod = 1".
11873
11874         surface.texture = &texture;
11875         surface.num_triangles = numtriangles;
11876         surface.num_firsttriangle = firsttriangle;
11877         surface.num_vertices = numvertices;
11878         surface.num_firstvertex = firstvertex;
11879
11880         // now render it
11881         rsurface.texture = R_GetCurrentTexture(surface.texture);
11882         rsurface.lightmaptexture = NULL;
11883         rsurface.deluxemaptexture = NULL;
11884         rsurface.uselightmaptexture = false;
11885         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11886 }
11887
11888 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)
11889 {
11890         static msurface_t surface;
11891         const msurface_t *surfacelist = &surface;
11892
11893         // fake enough texture and surface state to render this geometry
11894         surface.texture = texture;
11895         surface.num_triangles = numtriangles;
11896         surface.num_firsttriangle = firsttriangle;
11897         surface.num_vertices = numvertices;
11898         surface.num_firstvertex = firstvertex;
11899
11900         // now render it
11901         rsurface.texture = R_GetCurrentTexture(surface.texture);
11902         rsurface.lightmaptexture = NULL;
11903         rsurface.deluxemaptexture = NULL;
11904         rsurface.uselightmaptexture = false;
11905         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11906 }