]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix another C++ compile error
[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_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
166 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)"};
167 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
168 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)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
170 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)"};
171 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)"};
172 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
173 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"};
174 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."};
175 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184
185 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)"};
186 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
187 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"};
188 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
189 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
190 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
191 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"};
192 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"};
193 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)"};
194
195 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
196 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
197 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
198 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
199
200 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
201 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
202
203 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
204 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
205 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
206 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
207 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
208 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
209
210 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
211 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
212 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
213 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
214 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
217 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
218 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
219 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
220
221 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"};
222
223 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"};
224
225 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
226
227 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
228
229 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
230 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
231 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
232
233 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
234 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"};
235
236 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."};
237
238 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)"};
239
240 extern cvar_t v_glslgamma;
241 extern cvar_t v_glslgamma_2d;
242
243 extern qboolean v_flipped_state;
244
245 r_framebufferstate_t r_fb;
246
247 /// shadow volume bsp struct with automatically growing nodes buffer
248 svbsp_t r_svbsp;
249
250 rtexture_t *r_texture_blanknormalmap;
251 rtexture_t *r_texture_white;
252 rtexture_t *r_texture_grey128;
253 rtexture_t *r_texture_black;
254 rtexture_t *r_texture_notexture;
255 rtexture_t *r_texture_whitecube;
256 rtexture_t *r_texture_normalizationcube;
257 rtexture_t *r_texture_fogattenuation;
258 rtexture_t *r_texture_fogheighttexture;
259 rtexture_t *r_texture_gammaramps;
260 unsigned int r_texture_gammaramps_serial;
261 //rtexture_t *r_texture_fogintensity;
262 rtexture_t *r_texture_reflectcube;
263
264 // TODO: hash lookups?
265 typedef struct cubemapinfo_s
266 {
267         char basename[64];
268         rtexture_t *texture;
269 }
270 cubemapinfo_t;
271
272 int r_texture_numcubemaps;
273 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
274
275 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
276 unsigned int r_numqueries;
277 unsigned int r_maxqueries;
278
279 typedef struct r_qwskincache_s
280 {
281         char name[MAX_QPATH];
282         skinframe_t *skinframe;
283 }
284 r_qwskincache_t;
285
286 static r_qwskincache_t *r_qwskincache;
287 static int r_qwskincache_size;
288
289 /// vertex coordinates for a quad that covers the screen exactly
290 extern const float r_screenvertex3f[12];
291 extern const float r_d3dscreenvertex3f[12];
292 const float r_screenvertex3f[12] =
293 {
294         0, 0, 0,
295         1, 0, 0,
296         1, 1, 0,
297         0, 1, 0
298 };
299 const float r_d3dscreenvertex3f[12] =
300 {
301         0, 1, 0,
302         1, 1, 0,
303         1, 0, 0,
304         0, 0, 0
305 };
306
307 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
308 {
309         int i;
310         for (i = 0;i < verts;i++)
311         {
312                 out[0] = in[0] * r;
313                 out[1] = in[1] * g;
314                 out[2] = in[2] * b;
315                 out[3] = in[3];
316                 in += 4;
317                 out += 4;
318         }
319 }
320
321 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
322 {
323         int i;
324         for (i = 0;i < verts;i++)
325         {
326                 out[0] = r;
327                 out[1] = g;
328                 out[2] = b;
329                 out[3] = a;
330                 out += 4;
331         }
332 }
333
334 // FIXME: move this to client?
335 void FOG_clear(void)
336 {
337         if (gamemode == GAME_NEHAHRA)
338         {
339                 Cvar_Set("gl_fogenable", "0");
340                 Cvar_Set("gl_fogdensity", "0.2");
341                 Cvar_Set("gl_fogred", "0.3");
342                 Cvar_Set("gl_foggreen", "0.3");
343                 Cvar_Set("gl_fogblue", "0.3");
344         }
345         r_refdef.fog_density = 0;
346         r_refdef.fog_red = 0;
347         r_refdef.fog_green = 0;
348         r_refdef.fog_blue = 0;
349         r_refdef.fog_alpha = 1;
350         r_refdef.fog_start = 0;
351         r_refdef.fog_end = 16384;
352         r_refdef.fog_height = 1<<30;
353         r_refdef.fog_fadedepth = 128;
354         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
355 }
356
357 static void R_BuildBlankTextures(void)
358 {
359         unsigned char data[4];
360         data[2] = 128; // normal X
361         data[1] = 128; // normal Y
362         data[0] = 255; // normal Z
363         data[3] = 255; // height
364         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 255;
366         data[1] = 255;
367         data[2] = 255;
368         data[3] = 255;
369         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 128;
371         data[1] = 128;
372         data[2] = 128;
373         data[3] = 255;
374         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 0;
376         data[1] = 0;
377         data[2] = 0;
378         data[3] = 255;
379         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 }
381
382 static void R_BuildNoTexture(void)
383 {
384         int x, y;
385         unsigned char pix[16][16][4];
386         // this makes a light grey/dark grey checkerboard texture
387         for (y = 0;y < 16;y++)
388         {
389                 for (x = 0;x < 16;x++)
390                 {
391                         if ((y < 8) ^ (x < 8))
392                         {
393                                 pix[y][x][0] = 128;
394                                 pix[y][x][1] = 128;
395                                 pix[y][x][2] = 128;
396                                 pix[y][x][3] = 255;
397                         }
398                         else
399                         {
400                                 pix[y][x][0] = 64;
401                                 pix[y][x][1] = 64;
402                                 pix[y][x][2] = 64;
403                                 pix[y][x][3] = 255;
404                         }
405                 }
406         }
407         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildWhiteCube(void)
411 {
412         unsigned char data[6*1*1*4];
413         memset(data, 255, sizeof(data));
414         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
415 }
416
417 static void R_BuildNormalizationCube(void)
418 {
419         int x, y, side;
420         vec3_t v;
421         vec_t s, t, intensity;
422 #define NORMSIZE 64
423         unsigned char *data;
424         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
425         for (side = 0;side < 6;side++)
426         {
427                 for (y = 0;y < NORMSIZE;y++)
428                 {
429                         for (x = 0;x < NORMSIZE;x++)
430                         {
431                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
432                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
433                                 switch(side)
434                                 {
435                                 default:
436                                 case 0:
437                                         v[0] = 1;
438                                         v[1] = -t;
439                                         v[2] = -s;
440                                         break;
441                                 case 1:
442                                         v[0] = -1;
443                                         v[1] = -t;
444                                         v[2] = s;
445                                         break;
446                                 case 2:
447                                         v[0] = s;
448                                         v[1] = 1;
449                                         v[2] = t;
450                                         break;
451                                 case 3:
452                                         v[0] = s;
453                                         v[1] = -1;
454                                         v[2] = -t;
455                                         break;
456                                 case 4:
457                                         v[0] = s;
458                                         v[1] = -t;
459                                         v[2] = 1;
460                                         break;
461                                 case 5:
462                                         v[0] = -s;
463                                         v[1] = -t;
464                                         v[2] = -1;
465                                         break;
466                                 }
467                                 intensity = 127.0f / sqrt(DotProduct(v, v));
468                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
469                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
470                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
471                                 data[((side*64+y)*64+x)*4+3] = 255;
472                         }
473                 }
474         }
475         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
476         Mem_Free(data);
477 }
478
479 static void R_BuildFogTexture(void)
480 {
481         int x, b;
482 #define FOGWIDTH 256
483         unsigned char data1[FOGWIDTH][4];
484         //unsigned char data2[FOGWIDTH][4];
485         double d, r, alpha;
486
487         r_refdef.fogmasktable_start = r_refdef.fog_start;
488         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
489         r_refdef.fogmasktable_range = r_refdef.fogrange;
490         r_refdef.fogmasktable_density = r_refdef.fog_density;
491
492         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
493         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
494         {
495                 d = (x * r - r_refdef.fogmasktable_start);
496                 if(developer_extra.integer)
497                         Con_DPrintf("%f ", d);
498                 d = max(0, d);
499                 if (r_fog_exp2.integer)
500                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
501                 else
502                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
503                 if(developer_extra.integer)
504                         Con_DPrintf(" : %f ", alpha);
505                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
506                 if(developer_extra.integer)
507                         Con_DPrintf(" = %f\n", alpha);
508                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
509         }
510
511         for (x = 0;x < FOGWIDTH;x++)
512         {
513                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
514                 data1[x][0] = b;
515                 data1[x][1] = b;
516                 data1[x][2] = b;
517                 data1[x][3] = 255;
518                 //data2[x][0] = 255 - b;
519                 //data2[x][1] = 255 - b;
520                 //data2[x][2] = 255 - b;
521                 //data2[x][3] = 255;
522         }
523         if (r_texture_fogattenuation)
524         {
525                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
526                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
527         }
528         else
529         {
530                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
531                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
532         }
533 }
534
535 static void R_BuildFogHeightTexture(void)
536 {
537         unsigned char *inpixels;
538         int size;
539         int x;
540         int y;
541         int j;
542         float c[4];
543         float f;
544         inpixels = NULL;
545         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
546         if (r_refdef.fogheighttexturename[0])
547                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
548         if (!inpixels)
549         {
550                 r_refdef.fog_height_tablesize = 0;
551                 if (r_texture_fogheighttexture)
552                         R_FreeTexture(r_texture_fogheighttexture);
553                 r_texture_fogheighttexture = NULL;
554                 if (r_refdef.fog_height_table2d)
555                         Mem_Free(r_refdef.fog_height_table2d);
556                 r_refdef.fog_height_table2d = NULL;
557                 if (r_refdef.fog_height_table1d)
558                         Mem_Free(r_refdef.fog_height_table1d);
559                 r_refdef.fog_height_table1d = NULL;
560                 return;
561         }
562         size = image_width;
563         r_refdef.fog_height_tablesize = size;
564         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
565         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
566         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
567         Mem_Free(inpixels);
568         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
569         // average fog color table accounting for every fog layer between a point
570         // and the camera.  (Note: attenuation is handled separately!)
571         for (y = 0;y < size;y++)
572         {
573                 for (x = 0;x < size;x++)
574                 {
575                         Vector4Clear(c);
576                         f = 0;
577                         if (x < y)
578                         {
579                                 for (j = x;j <= y;j++)
580                                 {
581                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582                                         f++;
583                                 }
584                         }
585                         else
586                         {
587                                 for (j = x;j >= y;j--)
588                                 {
589                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
590                                         f++;
591                                 }
592                         }
593                         f = 1.0f / f;
594                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
595                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
596                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
597                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
598                 }
599         }
600         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
601 }
602
603 //=======================================================================================================================================================
604
605 static const char *builtinshaderstrings[] =
606 {
607 #include "shader_glsl.h"
608 0
609 };
610
611 const char *builtinhlslshaderstrings[] =
612 {
613 #include "shader_hlsl.h"
614 0
615 };
616
617 char *glslshaderstring = NULL;
618 char *hlslshaderstring = NULL;
619
620 //=======================================================================================================================================================
621
622 typedef struct shaderpermutationinfo_s
623 {
624         const char *pretext;
625         const char *name;
626 }
627 shaderpermutationinfo_t;
628
629 typedef struct shadermodeinfo_s
630 {
631         const char *filename;
632         const char *pretext;
633         const char *name;
634 }
635 shadermodeinfo_t;
636
637 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
638 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
639 {
640         {"#define USEDIFFUSE\n", " diffuse"},
641         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
642         {"#define USEVIEWTINT\n", " viewtint"},
643         {"#define USECOLORMAPPING\n", " colormapping"},
644         {"#define USESATURATION\n", " saturation"},
645         {"#define USEFOGINSIDE\n", " foginside"},
646         {"#define USEFOGOUTSIDE\n", " fogoutside"},
647         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
648         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
649         {"#define USEGAMMARAMPS\n", " gammaramps"},
650         {"#define USECUBEFILTER\n", " cubefilter"},
651         {"#define USEGLOW\n", " glow"},
652         {"#define USEBLOOM\n", " bloom"},
653         {"#define USESPECULAR\n", " specular"},
654         {"#define USEPOSTPROCESSING\n", " postprocessing"},
655         {"#define USEREFLECTION\n", " reflection"},
656         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
657         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
658         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
659         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
660         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
661         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
662         {"#define USEALPHAKILL\n", " alphakill"},
663         {"#define USEREFLECTCUBE\n", " reflectcube"},
664         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
665         {"#define USEBOUNCEGRID\n", " bouncegrid"},
666         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
667         {"#define USETRIPPY\n", " trippy"},
668         {"#define USEDEPTHRGB\n", " depthrgb"},
669         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
670         {"#define USESKELETAL\n", " skeletal"}
671 };
672
673 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
674 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
675 {
676         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
677         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
678         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
679         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
680         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
681         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
682         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
683         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
684         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
685         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
686         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
687         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
691         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
692         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
693 };
694
695 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
696 {
697         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
698         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
699         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
700         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
701         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
702         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
703         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
704         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
705         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
706         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
707         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
708         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenNormalMap;
753         int tex_Texture_ScreenDiffuse;
754         int tex_Texture_ScreenSpecular;
755         int tex_Texture_ReflectMask;
756         int tex_Texture_ReflectCube;
757         int tex_Texture_BounceGrid;
758         /// locations of detected uniforms in program object, or -1 if not found
759         int loc_Texture_First;
760         int loc_Texture_Second;
761         int loc_Texture_GammaRamps;
762         int loc_Texture_Normal;
763         int loc_Texture_Color;
764         int loc_Texture_Gloss;
765         int loc_Texture_Glow;
766         int loc_Texture_SecondaryNormal;
767         int loc_Texture_SecondaryColor;
768         int loc_Texture_SecondaryGloss;
769         int loc_Texture_SecondaryGlow;
770         int loc_Texture_Pants;
771         int loc_Texture_Shirt;
772         int loc_Texture_FogHeightTexture;
773         int loc_Texture_FogMask;
774         int loc_Texture_Lightmap;
775         int loc_Texture_Deluxemap;
776         int loc_Texture_Attenuation;
777         int loc_Texture_Cube;
778         int loc_Texture_Refraction;
779         int loc_Texture_Reflection;
780         int loc_Texture_ShadowMap2D;
781         int loc_Texture_CubeProjection;
782         int loc_Texture_ScreenNormalMap;
783         int loc_Texture_ScreenDiffuse;
784         int loc_Texture_ScreenSpecular;
785         int loc_Texture_ReflectMask;
786         int loc_Texture_ReflectCube;
787         int loc_Texture_BounceGrid;
788         int loc_Alpha;
789         int loc_BloomBlur_Parameters;
790         int loc_ClientTime;
791         int loc_Color_Ambient;
792         int loc_Color_Diffuse;
793         int loc_Color_Specular;
794         int loc_Color_Glow;
795         int loc_Color_Pants;
796         int loc_Color_Shirt;
797         int loc_DeferredColor_Ambient;
798         int loc_DeferredColor_Diffuse;
799         int loc_DeferredColor_Specular;
800         int loc_DeferredMod_Diffuse;
801         int loc_DeferredMod_Specular;
802         int loc_DistortScaleRefractReflect;
803         int loc_EyePosition;
804         int loc_FogColor;
805         int loc_FogHeightFade;
806         int loc_FogPlane;
807         int loc_FogPlaneViewDist;
808         int loc_FogRangeRecip;
809         int loc_LightColor;
810         int loc_LightDir;
811         int loc_LightPosition;
812         int loc_OffsetMapping_ScaleSteps;
813         int loc_OffsetMapping_LodDistance;
814         int loc_OffsetMapping_Bias;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_Skeletal_Transform12;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
863         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
864         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
865         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
866         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
867         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
868         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
869 };
870 #define SHADERSTATICPARMS_COUNT 13
871
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
874
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877
878 extern qboolean r_shadow_shadowmapsampler;
879 extern int r_shadow_shadowmappcf;
880 qboolean R_CompileShader_CheckStaticParms(void)
881 {
882         static int r_compileshader_staticparms_save[1];
883         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885
886         // detect all
887         if (r_glsl_saturation_redcompensate.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889         if (r_glsl_vertextextureblend_usebothalphas.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891         if (r_shadow_glossexact.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893         if (r_glsl_postprocess.integer)
894         {
895                 if (r_glsl_postprocess_uservec1_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897                 if (r_glsl_postprocess_uservec2_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899                 if (r_glsl_postprocess_uservec3_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901                 if (r_glsl_postprocess_uservec4_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
903         }
904         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
906
907         if (r_shadow_shadowmapsampler)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
909         if (r_shadow_shadowmappcf > 1)
910                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
911         else if (r_shadow_shadowmappcf)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
913         if (r_celshading.integer)
914                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
915         if (r_celoutlines.integer)
916                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
917
918         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
919 }
920
921 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
922         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
923                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
924         else \
925                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
926 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
927 {
928         shaderstaticparms_count = 0;
929
930         // emit all
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
943         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
944 }
945
946 /// information about each possible shader permutation
947 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
948 /// currently selected permutation
949 r_glsl_permutation_t *r_glsl_permutation;
950 /// storage for permutations linked in the hash table
951 memexpandablearray_t r_glsl_permutationarray;
952
953 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
954 {
955         //unsigned int hashdepth = 0;
956         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
957         r_glsl_permutation_t *p;
958         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
959         {
960                 if (p->mode == mode && p->permutation == permutation)
961                 {
962                         //if (hashdepth > 10)
963                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
964                         return p;
965                 }
966                 //hashdepth++;
967         }
968         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
969         p->mode = mode;
970         p->permutation = permutation;
971         p->hashnext = r_glsl_permutationhash[mode][hashindex];
972         r_glsl_permutationhash[mode][hashindex] = p;
973         //if (hashdepth > 10)
974         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
975         return p;
976 }
977
978 static char *R_ShaderStrCat(const char **strings)
979 {
980         char *string, *s;
981         const char **p = strings;
982         const char *t;
983         size_t len = 0;
984         for (p = strings;(t = *p);p++)
985                 len += strlen(t);
986         len++;
987         s = string = (char *)Mem_Alloc(r_main_mempool, len);
988         len = 0;
989         for (p = strings;(t = *p);p++)
990         {
991                 len = strlen(t);
992                 memcpy(s, t, len);
993                 s += len;
994         }
995         *s = 0;
996         return string;
997 }
998
999 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1000 {
1001         char *shaderstring;
1002         if (!filename || !filename[0])
1003                 return NULL;
1004         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1005         if (!strcmp(filename, "glsl/default.glsl"))
1006         {
1007                 if (builtinonly)
1008                         return R_ShaderStrCat(builtinshaderstrings);
1009                 if (!glslshaderstring)
1010                 {
1011                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1012                         if (glslshaderstring)
1013                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1014                         else
1015                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1016                 }
1017                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1018                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1019                 return shaderstring;
1020         }
1021         if (!strcmp(filename, "hlsl/default.hlsl"))
1022         {
1023                 if (builtinonly)
1024                         return R_ShaderStrCat(builtinhlslshaderstrings);
1025                 if (!hlslshaderstring)
1026                 {
1027                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1028                         if (hlslshaderstring)
1029                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1030                         else
1031                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1032                 }
1033                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1034                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1035                 return shaderstring;
1036         }
1037         // we don't have builtin strings for any other files
1038         if (builtinonly)
1039                 return NULL;
1040         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1041         if (shaderstring)
1042         {
1043                 if (printfromdisknotice)
1044                         Con_DPrintf("from disk %s... ", filename);
1045                 return shaderstring;
1046         }
1047         return shaderstring;
1048 }
1049
1050 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1051 {
1052         int i;
1053         int sampler;
1054         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1055         char *sourcestring;
1056         char permutationname[256];
1057         int vertstrings_count = 0;
1058         int geomstrings_count = 0;
1059         int fragstrings_count = 0;
1060         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1061         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1062         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1063
1064         if (p->compiled)
1065                 return;
1066         p->compiled = true;
1067         p->program = 0;
1068
1069         permutationname[0] = 0;
1070         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1071
1072         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1073
1074         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1075         if(vid.support.gl20shaders130)
1076         {
1077                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1078                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1079                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1080                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1081                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1082                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1083         }
1084
1085         // the first pretext is which type of shader to compile as
1086         // (later these will all be bound together as a program object)
1087         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1088         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1089         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1090
1091         // the second pretext is the mode (for example a light source)
1092         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1093         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1094         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1095         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1096
1097         // now add all the permutation pretexts
1098         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1099         {
1100                 if (permutation & (1<<i))
1101                 {
1102                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1103                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1104                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1105                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1106                 }
1107                 else
1108                 {
1109                         // keep line numbers correct
1110                         vertstrings_list[vertstrings_count++] = "\n";
1111                         geomstrings_list[geomstrings_count++] = "\n";
1112                         fragstrings_list[fragstrings_count++] = "\n";
1113                 }
1114         }
1115
1116         // add static parms
1117         R_CompileShader_AddStaticParms(mode, permutation);
1118         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1119         vertstrings_count += shaderstaticparms_count;
1120         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1121         geomstrings_count += shaderstaticparms_count;
1122         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1123         fragstrings_count += shaderstaticparms_count;
1124
1125         // now append the shader text itself
1126         vertstrings_list[vertstrings_count++] = sourcestring;
1127         geomstrings_list[geomstrings_count++] = sourcestring;
1128         fragstrings_list[fragstrings_count++] = sourcestring;
1129
1130         // compile the shader program
1131         if (vertstrings_count + geomstrings_count + fragstrings_count)
1132                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1133         if (p->program)
1134         {
1135                 CHECKGLERROR
1136                 qglUseProgram(p->program);CHECKGLERROR
1137                 // look up all the uniform variable names we care about, so we don't
1138                 // have to look them up every time we set them
1139
1140                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1141                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1142                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1143                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1144                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1145                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1146                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1147                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1148                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1149                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1150                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1151                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1152                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1153                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1154                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1155                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1156                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1157                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1158                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1159                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1160                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1161                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1162                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1163                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1164                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1165                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1166                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1167                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1168                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1169                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1170                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1171                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1172                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1173                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1174                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1175                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1176                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1177                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1178                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1179                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1180                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1181                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1182                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1183                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1184                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1185                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1186                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1187                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1188                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1189                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1190                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1191                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1192                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1193                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1194                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1195                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1196                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1197                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1198                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1199                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1200                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1201                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1202                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1203                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1204                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1205                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1206                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1207                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1208                 p->loc_Skeletal_Transform12       = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1209                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1210                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1211                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1212                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1213                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1214                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1215                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1216                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1217                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1218                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1219                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1220                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1221                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1222                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1223                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1224                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1225                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1226                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1227                 // initialize the samplers to refer to the texture units we use
1228                 p->tex_Texture_First = -1;
1229                 p->tex_Texture_Second = -1;
1230                 p->tex_Texture_GammaRamps = -1;
1231                 p->tex_Texture_Normal = -1;
1232                 p->tex_Texture_Color = -1;
1233                 p->tex_Texture_Gloss = -1;
1234                 p->tex_Texture_Glow = -1;
1235                 p->tex_Texture_SecondaryNormal = -1;
1236                 p->tex_Texture_SecondaryColor = -1;
1237                 p->tex_Texture_SecondaryGloss = -1;
1238                 p->tex_Texture_SecondaryGlow = -1;
1239                 p->tex_Texture_Pants = -1;
1240                 p->tex_Texture_Shirt = -1;
1241                 p->tex_Texture_FogHeightTexture = -1;
1242                 p->tex_Texture_FogMask = -1;
1243                 p->tex_Texture_Lightmap = -1;
1244                 p->tex_Texture_Deluxemap = -1;
1245                 p->tex_Texture_Attenuation = -1;
1246                 p->tex_Texture_Cube = -1;
1247                 p->tex_Texture_Refraction = -1;
1248                 p->tex_Texture_Reflection = -1;
1249                 p->tex_Texture_ShadowMap2D = -1;
1250                 p->tex_Texture_CubeProjection = -1;
1251                 p->tex_Texture_ScreenNormalMap = -1;
1252                 p->tex_Texture_ScreenDiffuse = -1;
1253                 p->tex_Texture_ScreenSpecular = -1;
1254                 p->tex_Texture_ReflectMask = -1;
1255                 p->tex_Texture_ReflectCube = -1;
1256                 p->tex_Texture_BounceGrid = -1;
1257                 sampler = 0;
1258                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1259                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1260                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1261                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1262                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1263                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1264                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1265                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1266                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1267                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1268                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1269                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1270                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1271                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1272                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1273                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1274                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1275                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1276                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1277                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1278                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1279                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1280                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1281                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1282                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1283                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1284                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1285                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1286                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1287                 CHECKGLERROR
1288                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1289         }
1290         else
1291                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1292
1293         // free the strings
1294         if (sourcestring)
1295                 Mem_Free(sourcestring);
1296 }
1297
1298 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1299 {
1300         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1301         if (r_glsl_permutation != perm)
1302         {
1303                 r_glsl_permutation = perm;
1304                 if (!r_glsl_permutation->program)
1305                 {
1306                         if (!r_glsl_permutation->compiled)
1307                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1308                         if (!r_glsl_permutation->program)
1309                         {
1310                                 // remove features until we find a valid permutation
1311                                 int i;
1312                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1313                                 {
1314                                         // reduce i more quickly whenever it would not remove any bits
1315                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1316                                         if (!(permutation & j))
1317                                                 continue;
1318                                         permutation -= j;
1319                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1320                                         if (!r_glsl_permutation->compiled)
1321                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1322                                         if (r_glsl_permutation->program)
1323                                                 break;
1324                                 }
1325                                 if (i >= SHADERPERMUTATION_COUNT)
1326                                 {
1327                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1328                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1329                                         qglUseProgram(0);CHECKGLERROR
1330                                         return; // no bit left to clear, entire mode is broken
1331                                 }
1332                         }
1333                 }
1334                 CHECKGLERROR
1335                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1336         }
1337         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1338         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1339         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1340 }
1341
1342 #ifdef SUPPORTD3D
1343
1344 #ifdef SUPPORTD3D
1345 #include <d3d9.h>
1346 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1347 extern D3DCAPS9 vid_d3d9caps;
1348 #endif
1349
1350 struct r_hlsl_permutation_s;
1351 typedef struct r_hlsl_permutation_s
1352 {
1353         /// hash lookup data
1354         struct r_hlsl_permutation_s *hashnext;
1355         unsigned int mode;
1356         unsigned int permutation;
1357
1358         /// indicates if we have tried compiling this permutation already
1359         qboolean compiled;
1360         /// NULL if compilation failed
1361         IDirect3DVertexShader9 *vertexshader;
1362         IDirect3DPixelShader9 *pixelshader;
1363 }
1364 r_hlsl_permutation_t;
1365
1366 typedef enum D3DVSREGISTER_e
1367 {
1368         D3DVSREGISTER_TexMatrix = 0, // float4x4
1369         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1370         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1371         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1372         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1373         D3DVSREGISTER_ModelToLight = 20, // float4x4
1374         D3DVSREGISTER_EyePosition = 24,
1375         D3DVSREGISTER_FogPlane = 25,
1376         D3DVSREGISTER_LightDir = 26,
1377         D3DVSREGISTER_LightPosition = 27,
1378 }
1379 D3DVSREGISTER_t;
1380
1381 typedef enum D3DPSREGISTER_e
1382 {
1383         D3DPSREGISTER_Alpha = 0,
1384         D3DPSREGISTER_BloomBlur_Parameters = 1,
1385         D3DPSREGISTER_ClientTime = 2,
1386         D3DPSREGISTER_Color_Ambient = 3,
1387         D3DPSREGISTER_Color_Diffuse = 4,
1388         D3DPSREGISTER_Color_Specular = 5,
1389         D3DPSREGISTER_Color_Glow = 6,
1390         D3DPSREGISTER_Color_Pants = 7,
1391         D3DPSREGISTER_Color_Shirt = 8,
1392         D3DPSREGISTER_DeferredColor_Ambient = 9,
1393         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1394         D3DPSREGISTER_DeferredColor_Specular = 11,
1395         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1396         D3DPSREGISTER_DeferredMod_Specular = 13,
1397         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1398         D3DPSREGISTER_EyePosition = 15, // unused
1399         D3DPSREGISTER_FogColor = 16,
1400         D3DPSREGISTER_FogHeightFade = 17,
1401         D3DPSREGISTER_FogPlane = 18,
1402         D3DPSREGISTER_FogPlaneViewDist = 19,
1403         D3DPSREGISTER_FogRangeRecip = 20,
1404         D3DPSREGISTER_LightColor = 21,
1405         D3DPSREGISTER_LightDir = 22, // unused
1406         D3DPSREGISTER_LightPosition = 23,
1407         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1408         D3DPSREGISTER_PixelSize = 25,
1409         D3DPSREGISTER_ReflectColor = 26,
1410         D3DPSREGISTER_ReflectFactor = 27,
1411         D3DPSREGISTER_ReflectOffset = 28,
1412         D3DPSREGISTER_RefractColor = 29,
1413         D3DPSREGISTER_Saturation = 30,
1414         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1415         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1416         D3DPSREGISTER_ScreenToDepth = 33,
1417         D3DPSREGISTER_ShadowMap_Parameters = 34,
1418         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1419         D3DPSREGISTER_SpecularPower = 36,
1420         D3DPSREGISTER_UserVec1 = 37,
1421         D3DPSREGISTER_UserVec2 = 38,
1422         D3DPSREGISTER_UserVec3 = 39,
1423         D3DPSREGISTER_UserVec4 = 40,
1424         D3DPSREGISTER_ViewTintColor = 41,
1425         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1426         D3DPSREGISTER_BloomColorSubtract = 43,
1427         D3DPSREGISTER_ViewToLight = 44, // float4x4
1428         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1429         D3DPSREGISTER_NormalmapScrollBlend = 52,
1430         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1431         D3DPSREGISTER_OffsetMapping_Bias = 54,
1432         // next at 54
1433 }
1434 D3DPSREGISTER_t;
1435
1436 /// information about each possible shader permutation
1437 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1438 /// currently selected permutation
1439 r_hlsl_permutation_t *r_hlsl_permutation;
1440 /// storage for permutations linked in the hash table
1441 memexpandablearray_t r_hlsl_permutationarray;
1442
1443 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1444 {
1445         //unsigned int hashdepth = 0;
1446         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1447         r_hlsl_permutation_t *p;
1448         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1449         {
1450                 if (p->mode == mode && p->permutation == permutation)
1451                 {
1452                         //if (hashdepth > 10)
1453                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1454                         return p;
1455                 }
1456                 //hashdepth++;
1457         }
1458         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1459         p->mode = mode;
1460         p->permutation = permutation;
1461         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1462         r_hlsl_permutationhash[mode][hashindex] = p;
1463         //if (hashdepth > 10)
1464         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1465         return p;
1466 }
1467
1468 #include <d3dx9.h>
1469 //#include <d3dx9shader.h>
1470 //#include <d3dx9mesh.h>
1471
1472 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1473 {
1474         DWORD *vsbin = NULL;
1475         DWORD *psbin = NULL;
1476         fs_offset_t vsbinsize;
1477         fs_offset_t psbinsize;
1478 //      IDirect3DVertexShader9 *vs = NULL;
1479 //      IDirect3DPixelShader9 *ps = NULL;
1480         ID3DXBuffer *vslog = NULL;
1481         ID3DXBuffer *vsbuffer = NULL;
1482         ID3DXConstantTable *vsconstanttable = NULL;
1483         ID3DXBuffer *pslog = NULL;
1484         ID3DXBuffer *psbuffer = NULL;
1485         ID3DXConstantTable *psconstanttable = NULL;
1486         int vsresult = 0;
1487         int psresult = 0;
1488         char temp[MAX_INPUTLINE];
1489         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1490         char vabuf[1024];
1491         qboolean debugshader = gl_paranoid.integer != 0;
1492         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1493         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1494         if (!debugshader)
1495         {
1496                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1497                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1498         }
1499         if ((!vsbin && vertstring) || (!psbin && fragstring))
1500         {
1501                 const char* dllnames_d3dx9 [] =
1502                 {
1503                         "d3dx9_43.dll",
1504                         "d3dx9_42.dll",
1505                         "d3dx9_41.dll",
1506                         "d3dx9_40.dll",
1507                         "d3dx9_39.dll",
1508                         "d3dx9_38.dll",
1509                         "d3dx9_37.dll",
1510                         "d3dx9_36.dll",
1511                         "d3dx9_35.dll",
1512                         "d3dx9_34.dll",
1513                         "d3dx9_33.dll",
1514                         "d3dx9_32.dll",
1515                         "d3dx9_31.dll",
1516                         "d3dx9_30.dll",
1517                         "d3dx9_29.dll",
1518                         "d3dx9_28.dll",
1519                         "d3dx9_27.dll",
1520                         "d3dx9_26.dll",
1521                         "d3dx9_25.dll",
1522                         "d3dx9_24.dll",
1523                         NULL
1524                 };
1525                 dllhandle_t d3dx9_dll = NULL;
1526                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1527                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1528                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1529                 dllfunction_t d3dx9_dllfuncs[] =
1530                 {
1531                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1532                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1533                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1534                         {NULL, NULL}
1535                 };
1536                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1537                 {
1538                         DWORD shaderflags = 0;
1539                         if (debugshader)
1540                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1541                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1542                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1543                         if (vertstring && vertstring[0])
1544                         {
1545                                 if (debugshader)
1546                                 {
1547                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1548                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1549                                 }
1550                                 else
1551                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1552                                 if (vsbuffer)
1553                                 {
1554                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1555                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1556                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1557                                         ID3DXBuffer_Release(vsbuffer);
1558                                 }
1559                                 if (vslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1562                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         ID3DXBuffer_Release(vslog);
1564                                 }
1565                         }
1566                         if (fragstring && fragstring[0])
1567                         {
1568                                 if (debugshader)
1569                                 {
1570                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1571                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1572                                 }
1573                                 else
1574                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1575                                 if (psbuffer)
1576                                 {
1577                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1578                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1579                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1580                                         ID3DXBuffer_Release(psbuffer);
1581                                 }
1582                                 if (pslog)
1583                                 {
1584                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1585                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1586                                         ID3DXBuffer_Release(pslog);
1587                                 }
1588                         }
1589                         Sys_UnloadLibrary(&d3dx9_dll);
1590                 }
1591                 else
1592                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1593         }
1594         if (vsbin && psbin)
1595         {
1596                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1597                 if (FAILED(vsresult))
1598                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1599                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1600                 if (FAILED(psresult))
1601                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1602         }
1603         // free the shader data
1604         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1605         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1606 }
1607
1608 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1609 {
1610         int i;
1611         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1612         int vertstring_length = 0;
1613         int geomstring_length = 0;
1614         int fragstring_length = 0;
1615         char *t;
1616         char *sourcestring;
1617         char *vertstring, *geomstring, *fragstring;
1618         char permutationname[256];
1619         char cachename[256];
1620         int vertstrings_count = 0;
1621         int geomstrings_count = 0;
1622         int fragstrings_count = 0;
1623         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1624         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1625         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1626
1627         if (p->compiled)
1628                 return;
1629         p->compiled = true;
1630         p->vertexshader = NULL;
1631         p->pixelshader = NULL;
1632
1633         permutationname[0] = 0;
1634         cachename[0] = 0;
1635         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1636
1637         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1638         strlcat(cachename, "hlsl/", sizeof(cachename));
1639
1640         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1641         vertstrings_count = 0;
1642         geomstrings_count = 0;
1643         fragstrings_count = 0;
1644         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1645         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1646         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1647
1648         // the first pretext is which type of shader to compile as
1649         // (later these will all be bound together as a program object)
1650         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1651         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1652         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1653
1654         // the second pretext is the mode (for example a light source)
1655         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1656         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1657         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1658         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1659         strlcat(cachename, modeinfo->name, sizeof(cachename));
1660
1661         // now add all the permutation pretexts
1662         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1663         {
1664                 if (permutation & (1<<i))
1665                 {
1666                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1667                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1668                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1669                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1670                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1671                 }
1672                 else
1673                 {
1674                         // keep line numbers correct
1675                         vertstrings_list[vertstrings_count++] = "\n";
1676                         geomstrings_list[geomstrings_count++] = "\n";
1677                         fragstrings_list[fragstrings_count++] = "\n";
1678                 }
1679         }
1680
1681         // add static parms
1682         R_CompileShader_AddStaticParms(mode, permutation);
1683         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684         vertstrings_count += shaderstaticparms_count;
1685         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686         geomstrings_count += shaderstaticparms_count;
1687         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1688         fragstrings_count += shaderstaticparms_count;
1689
1690         // replace spaces in the cachename with _ characters
1691         for (i = 0;cachename[i];i++)
1692                 if (cachename[i] == ' ')
1693                         cachename[i] = '_';
1694
1695         // now append the shader text itself
1696         vertstrings_list[vertstrings_count++] = sourcestring;
1697         geomstrings_list[geomstrings_count++] = sourcestring;
1698         fragstrings_list[fragstrings_count++] = sourcestring;
1699
1700         vertstring_length = 0;
1701         for (i = 0;i < vertstrings_count;i++)
1702                 vertstring_length += strlen(vertstrings_list[i]);
1703         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1704         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1705                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1706
1707         geomstring_length = 0;
1708         for (i = 0;i < geomstrings_count;i++)
1709                 geomstring_length += strlen(geomstrings_list[i]);
1710         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1711         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1712                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1713
1714         fragstring_length = 0;
1715         for (i = 0;i < fragstrings_count;i++)
1716                 fragstring_length += strlen(fragstrings_list[i]);
1717         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1718         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1719                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1720
1721         // try to load the cached shader, or generate one
1722         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1723
1724         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1725                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1726         else
1727                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1728
1729         // free the strings
1730         if (vertstring)
1731                 Mem_Free(vertstring);
1732         if (geomstring)
1733                 Mem_Free(geomstring);
1734         if (fragstring)
1735                 Mem_Free(fragstring);
1736         if (sourcestring)
1737                 Mem_Free(sourcestring);
1738 }
1739
1740 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1741 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1742 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);}
1743 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);}
1744 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);}
1745 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);}
1746
1747 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1748 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1749 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);}
1750 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);}
1751 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);}
1752 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);}
1753
1754 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1755 {
1756         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1757         if (r_hlsl_permutation != perm)
1758         {
1759                 r_hlsl_permutation = perm;
1760                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1761                 {
1762                         if (!r_hlsl_permutation->compiled)
1763                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1764                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1765                         {
1766                                 // remove features until we find a valid permutation
1767                                 int i;
1768                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1769                                 {
1770                                         // reduce i more quickly whenever it would not remove any bits
1771                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1772                                         if (!(permutation & j))
1773                                                 continue;
1774                                         permutation -= j;
1775                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776                                         if (!r_hlsl_permutation->compiled)
1777                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1778                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1779                                                 break;
1780                                 }
1781                                 if (i >= SHADERPERMUTATION_COUNT)
1782                                 {
1783                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1784                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1785                                         return; // no bit left to clear, entire mode is broken
1786                                 }
1787                         }
1788                 }
1789                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1790                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1791         }
1792         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1793         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1794         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1795 }
1796 #endif
1797
1798 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1799 {
1800         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1801         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1802         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1803         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1804 }
1805
1806 void R_GLSL_Restart_f(void)
1807 {
1808         unsigned int i, limit;
1809         if (glslshaderstring)
1810                 Mem_Free(glslshaderstring);
1811         glslshaderstring = NULL;
1812         if (hlslshaderstring)
1813                 Mem_Free(hlslshaderstring);
1814         hlslshaderstring = NULL;
1815         switch(vid.renderpath)
1816         {
1817         case RENDERPATH_D3D9:
1818 #ifdef SUPPORTD3D
1819                 {
1820                         r_hlsl_permutation_t *p;
1821                         r_hlsl_permutation = NULL;
1822                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1823                         for (i = 0;i < limit;i++)
1824                         {
1825                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1826                                 {
1827                                         if (p->vertexshader)
1828                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1829                                         if (p->pixelshader)
1830                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1831                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1832                                 }
1833                         }
1834                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1835                 }
1836 #endif
1837                 break;
1838         case RENDERPATH_D3D10:
1839                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840                 break;
1841         case RENDERPATH_D3D11:
1842                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1843                 break;
1844         case RENDERPATH_GL20:
1845         case RENDERPATH_GLES2:
1846                 {
1847                         r_glsl_permutation_t *p;
1848                         r_glsl_permutation = NULL;
1849                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1850                         for (i = 0;i < limit;i++)
1851                         {
1852                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1853                                 {
1854                                         GL_Backend_FreeProgram(p->program);
1855                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1856                                 }
1857                         }
1858                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1859                 }
1860                 break;
1861         case RENDERPATH_GL11:
1862         case RENDERPATH_GL13:
1863         case RENDERPATH_GLES1:
1864                 break;
1865         case RENDERPATH_SOFT:
1866                 break;
1867         }
1868 }
1869
1870 static void R_GLSL_DumpShader_f(void)
1871 {
1872         int i, language, mode, dupe;
1873         char *text;
1874         shadermodeinfo_t *modeinfo;
1875         qfile_t *file;
1876
1877         for (language = 0;language < 2;language++)
1878         {
1879                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1880                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1881                 {
1882                         // don't dump the same file multiple times (most or all shaders come from the same file)
1883                         for (dupe = mode - 1;dupe >= 0;dupe--)
1884                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1885                                         break;
1886                         if (dupe >= 0)
1887                                 continue;
1888                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1889                         if (!text)
1890                                 continue;
1891                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1892                         if (file)
1893                         {
1894                                 FS_Print(file, "/* The engine may define the following macros:\n");
1895                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1896                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1897                                         FS_Print(file, modeinfo[i].pretext);
1898                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1899                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1900                                 FS_Print(file, "*/\n");
1901                                 FS_Print(file, text);
1902                                 FS_Close(file);
1903                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1904                         }
1905                         else
1906                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1907                         Mem_Free(text);
1908                 }
1909         }
1910 }
1911
1912 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1913 {
1914         unsigned int permutation = 0;
1915         if (r_trippy.integer && !notrippy)
1916                 permutation |= SHADERPERMUTATION_TRIPPY;
1917         permutation |= SHADERPERMUTATION_VIEWTINT;
1918         if (first)
1919                 permutation |= SHADERPERMUTATION_DIFFUSE;
1920         if (second)
1921                 permutation |= SHADERPERMUTATION_SPECULAR;
1922         if (texturemode == GL_MODULATE)
1923                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1924         else if (texturemode == GL_ADD)
1925                 permutation |= SHADERPERMUTATION_GLOW;
1926         else if (texturemode == GL_DECAL)
1927                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1928         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1929                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1930         if (suppresstexalpha)
1931                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1932         if (!second)
1933                 texturemode = GL_MODULATE;
1934         if (vid.allowalphatocoverage)
1935                 GL_AlphaToCoverage(false);
1936         switch (vid.renderpath)
1937         {
1938         case RENDERPATH_D3D9:
1939 #ifdef SUPPORTD3D
1940                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1941                 R_Mesh_TexBind(GL20TU_FIRST , first );
1942                 R_Mesh_TexBind(GL20TU_SECOND, second);
1943                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1944                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1945 #endif
1946                 break;
1947         case RENDERPATH_D3D10:
1948                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949                 break;
1950         case RENDERPATH_D3D11:
1951                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952                 break;
1953         case RENDERPATH_GL20:
1954         case RENDERPATH_GLES2:
1955                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1956                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1957                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1958                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1959                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1960                 break;
1961         case RENDERPATH_GL13:
1962         case RENDERPATH_GLES1:
1963                 R_Mesh_TexBind(0, first );
1964                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1965                 R_Mesh_TexBind(1, second);
1966                 if (second)
1967                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1968                 break;
1969         case RENDERPATH_GL11:
1970                 R_Mesh_TexBind(0, first );
1971                 break;
1972         case RENDERPATH_SOFT:
1973                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1974                 R_Mesh_TexBind(GL20TU_FIRST , first );
1975                 R_Mesh_TexBind(GL20TU_SECOND, second);
1976                 break;
1977         }
1978 }
1979
1980 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1981 {
1982         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1983 }
1984
1985 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1986 {
1987         unsigned int permutation = 0;
1988         if (r_trippy.integer && !notrippy)
1989                 permutation |= SHADERPERMUTATION_TRIPPY;
1990         if (depthrgb)
1991                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1992         if (skeletal)
1993                 permutation |= SHADERPERMUTATION_SKELETAL;
1994
1995         if (vid.allowalphatocoverage)
1996                 GL_AlphaToCoverage(false);
1997         switch (vid.renderpath)
1998         {
1999         case RENDERPATH_D3D9:
2000 #ifdef SUPPORTD3D
2001                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2002 #endif
2003                 break;
2004         case RENDERPATH_D3D10:
2005                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2006                 break;
2007         case RENDERPATH_D3D11:
2008                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2009                 break;
2010         case RENDERPATH_GL20:
2011         case RENDERPATH_GLES2:
2012                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2013                 break;
2014         case RENDERPATH_GL13:
2015         case RENDERPATH_GLES1:
2016                 R_Mesh_TexBind(0, 0);
2017                 R_Mesh_TexBind(1, 0);
2018                 break;
2019         case RENDERPATH_GL11:
2020                 R_Mesh_TexBind(0, 0);
2021                 break;
2022         case RENDERPATH_SOFT:
2023                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2024                 break;
2025         }
2026 }
2027
2028 extern qboolean r_shadow_usingdeferredprepass;
2029 extern rtexture_t *r_shadow_attenuationgradienttexture;
2030 extern rtexture_t *r_shadow_attenuation2dtexture;
2031 extern rtexture_t *r_shadow_attenuation3dtexture;
2032 extern qboolean r_shadow_usingshadowmap2d;
2033 extern qboolean r_shadow_usingshadowmaportho;
2034 extern float r_shadow_shadowmap_texturescale[2];
2035 extern float r_shadow_shadowmap_parameters[4];
2036 extern qboolean r_shadow_shadowmapvsdct;
2037 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2038 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2039 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2040 extern matrix4x4_t r_shadow_shadowmapmatrix;
2041 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2042 extern int r_shadow_prepass_width;
2043 extern int r_shadow_prepass_height;
2044 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2045 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2046 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2047 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2048
2049 #define BLENDFUNC_ALLOWS_COLORMOD      1
2050 #define BLENDFUNC_ALLOWS_FOG           2
2051 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2052 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2053 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2054 static int R_BlendFuncFlags(int src, int dst)
2055 {
2056         int r = 0;
2057
2058         // a blendfunc allows colormod if:
2059         // a) it can never keep the destination pixel invariant, or
2060         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2061         // this is to prevent unintended side effects from colormod
2062
2063         // a blendfunc allows fog if:
2064         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2065         // this is to prevent unintended side effects from fog
2066
2067         // these checks are the output of fogeval.pl
2068
2069         r |= BLENDFUNC_ALLOWS_COLORMOD;
2070         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2071         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2072         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2073         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2074         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2075         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2078         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2079         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2080         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2081         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2082         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2083         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2084         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2085         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2086         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091
2092         return r;
2093 }
2094
2095 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)
2096 {
2097         // select a permutation of the lighting shader appropriate to this
2098         // combination of texture, entity, light source, and fogging, only use the
2099         // minimum features necessary to avoid wasting rendering time in the
2100         // fragment shader on features that are not being used
2101         unsigned int permutation = 0;
2102         unsigned int mode = 0;
2103         int blendfuncflags;
2104         static float dummy_colormod[3] = {1, 1, 1};
2105         float *colormod = rsurface.colormod;
2106         float m16f[16];
2107         matrix4x4_t tempmatrix;
2108         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2109         if (r_trippy.integer && !notrippy)
2110                 permutation |= SHADERPERMUTATION_TRIPPY;
2111         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2112                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2113         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2114                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2115         if (rsurfacepass == RSURFPASS_BACKGROUND)
2116         {
2117                 // distorted background
2118                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2119                 {
2120                         mode = SHADERMODE_WATER;
2121                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2122                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2123                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2124                         {
2125                                 // this is the right thing to do for wateralpha
2126                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2127                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2128                         }
2129                         else
2130                         {
2131                                 // this is the right thing to do for entity alpha
2132                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2133                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2134                         }
2135                 }
2136                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2137                 {
2138                         mode = SHADERMODE_REFRACTION;
2139                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2140                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2141                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2142                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2143                 }
2144                 else
2145                 {
2146                         mode = SHADERMODE_GENERIC;
2147                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2148                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2149                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2150                 }
2151                 if (vid.allowalphatocoverage)
2152                         GL_AlphaToCoverage(false);
2153         }
2154         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2155         {
2156                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2157                 {
2158                         switch(rsurface.texture->offsetmapping)
2159                         {
2160                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2161                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2162                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2163                         case OFFSETMAPPING_OFF: break;
2164                         }
2165                 }
2166                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2167                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2168                 // normalmap (deferred prepass), may use alpha test on diffuse
2169                 mode = SHADERMODE_DEFERREDGEOMETRY;
2170                 GL_BlendFunc(GL_ONE, GL_ZERO);
2171                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2172                 if (vid.allowalphatocoverage)
2173                         GL_AlphaToCoverage(false);
2174         }
2175         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2176         {
2177                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2178                 {
2179                         switch(rsurface.texture->offsetmapping)
2180                         {
2181                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2182                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2183                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2184                         case OFFSETMAPPING_OFF: break;
2185                         }
2186                 }
2187                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2188                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2189                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2190                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2191                 // light source
2192                 mode = SHADERMODE_LIGHTSOURCE;
2193                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2194                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2195                 if (diffusescale > 0)
2196                         permutation |= SHADERPERMUTATION_DIFFUSE;
2197                 if (specularscale > 0)
2198                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2199                 if (r_refdef.fogenabled)
2200                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2201                 if (rsurface.texture->colormapping)
2202                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2203                 if (r_shadow_usingshadowmap2d)
2204                 {
2205                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2206                         if(r_shadow_shadowmapvsdct)
2207                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2208
2209                         if (r_shadow_shadowmap2ddepthbuffer)
2210                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2211                 }
2212                 if (rsurface.texture->reflectmasktexture)
2213                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2214                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2215                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2216                 if (vid.allowalphatocoverage)
2217                         GL_AlphaToCoverage(false);
2218         }
2219         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2220         {
2221                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2222                 {
2223                         switch(rsurface.texture->offsetmapping)
2224                         {
2225                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2226                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2227                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2228                         case OFFSETMAPPING_OFF: break;
2229                         }
2230                 }
2231                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2232                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2233                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2234                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2235                 // unshaded geometry (fullbright or ambient model lighting)
2236                 mode = SHADERMODE_FLATCOLOR;
2237                 ambientscale = diffusescale = specularscale = 0;
2238                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2239                         permutation |= SHADERPERMUTATION_GLOW;
2240                 if (r_refdef.fogenabled)
2241                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2242                 if (rsurface.texture->colormapping)
2243                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2244                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2245                 {
2246                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2247                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2248
2249                         if (r_shadow_shadowmap2ddepthbuffer)
2250                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2251                 }
2252                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2253                         permutation |= SHADERPERMUTATION_REFLECTION;
2254                 if (rsurface.texture->reflectmasktexture)
2255                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2256                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2257                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2258                 // when using alphatocoverage, we don't need alphakill
2259                 if (vid.allowalphatocoverage)
2260                 {
2261                         if (r_transparent_alphatocoverage.integer)
2262                         {
2263                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2264                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2265                         }
2266                         else
2267                                 GL_AlphaToCoverage(false);
2268                 }
2269         }
2270         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2271         {
2272                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2273                 {
2274                         switch(rsurface.texture->offsetmapping)
2275                         {
2276                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2277                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2278                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279                         case OFFSETMAPPING_OFF: break;
2280                         }
2281                 }
2282                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2283                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2285                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2286                 // directional model lighting
2287                 mode = SHADERMODE_LIGHTDIRECTION;
2288                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2289                         permutation |= SHADERPERMUTATION_GLOW;
2290                 permutation |= SHADERPERMUTATION_DIFFUSE;
2291                 if (specularscale > 0)
2292                         permutation |= SHADERPERMUTATION_SPECULAR;
2293                 if (r_refdef.fogenabled)
2294                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2295                 if (rsurface.texture->colormapping)
2296                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2297                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2298                 {
2299                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2300                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2301
2302                         if (r_shadow_shadowmap2ddepthbuffer)
2303                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2304                 }
2305                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2306                         permutation |= SHADERPERMUTATION_REFLECTION;
2307                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2308                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2309                 if (rsurface.texture->reflectmasktexture)
2310                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2311                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2312                 {
2313                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2314                         if (r_shadow_bouncegriddirectional)
2315                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2316                 }
2317                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2318                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2319                 // when using alphatocoverage, we don't need alphakill
2320                 if (vid.allowalphatocoverage)
2321                 {
2322                         if (r_transparent_alphatocoverage.integer)
2323                         {
2324                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2325                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2326                         }
2327                         else
2328                                 GL_AlphaToCoverage(false);
2329                 }
2330         }
2331         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2332         {
2333                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2334                 {
2335                         switch(rsurface.texture->offsetmapping)
2336                         {
2337                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2338                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2339                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2340                         case OFFSETMAPPING_OFF: break;
2341                         }
2342                 }
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2344                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2345                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2346                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2347                 // ambient model lighting
2348                 mode = SHADERMODE_LIGHTDIRECTION;
2349                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2350                         permutation |= SHADERPERMUTATION_GLOW;
2351                 if (r_refdef.fogenabled)
2352                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2353                 if (rsurface.texture->colormapping)
2354                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2355                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2356                 {
2357                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2358                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2359
2360                         if (r_shadow_shadowmap2ddepthbuffer)
2361                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2362                 }
2363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364                         permutation |= SHADERPERMUTATION_REFLECTION;
2365                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2370                 {
2371                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2372                         if (r_shadow_bouncegriddirectional)
2373                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2374                 }
2375                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2376                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2377                 // when using alphatocoverage, we don't need alphakill
2378                 if (vid.allowalphatocoverage)
2379                 {
2380                         if (r_transparent_alphatocoverage.integer)
2381                         {
2382                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2383                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2384                         }
2385                         else
2386                                 GL_AlphaToCoverage(false);
2387                 }
2388         }
2389         else
2390         {
2391                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2392                 {
2393                         switch(rsurface.texture->offsetmapping)
2394                         {
2395                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2396                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2397                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2398                         case OFFSETMAPPING_OFF: break;
2399                         }
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2402                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2404                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2405                 // lightmapped wall
2406                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2407                         permutation |= SHADERPERMUTATION_GLOW;
2408                 if (r_refdef.fogenabled)
2409                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2410                 if (rsurface.texture->colormapping)
2411                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2412                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2413                 {
2414                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2415                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2416
2417                         if (r_shadow_shadowmap2ddepthbuffer)
2418                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2419                 }
2420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2421                         permutation |= SHADERPERMUTATION_REFLECTION;
2422                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2423                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2424                 if (rsurface.texture->reflectmasktexture)
2425                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2426                 if (FAKELIGHT_ENABLED)
2427                 {
2428                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2429                         mode = SHADERMODE_FAKELIGHT;
2430                         permutation |= SHADERPERMUTATION_DIFFUSE;
2431                         if (specularscale > 0)
2432                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2433                 }
2434                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2435                 {
2436                         // deluxemapping (light direction texture)
2437                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2438                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2439                         else
2440                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2441                         permutation |= SHADERPERMUTATION_DIFFUSE;
2442                         if (specularscale > 0)
2443                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2444                 }
2445                 else if (r_glsl_deluxemapping.integer >= 2)
2446                 {
2447                         // fake deluxemapping (uniform light direction in tangentspace)
2448                         if (rsurface.uselightmaptexture)
2449                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2450                         else
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2452                         permutation |= SHADERPERMUTATION_DIFFUSE;
2453                         if (specularscale > 0)
2454                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2455                 }
2456                 else if (rsurface.uselightmaptexture)
2457                 {
2458                         // ordinary lightmapping (q1bsp, q3bsp)
2459                         mode = SHADERMODE_LIGHTMAP;
2460                 }
2461                 else
2462                 {
2463                         // ordinary vertex coloring (q3bsp)
2464                         mode = SHADERMODE_VERTEXCOLOR;
2465                 }
2466                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2467                 {
2468                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2469                         if (r_shadow_bouncegriddirectional)
2470                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2471                 }
2472                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2473                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2474                 // when using alphatocoverage, we don't need alphakill
2475                 if (vid.allowalphatocoverage)
2476                 {
2477                         if (r_transparent_alphatocoverage.integer)
2478                         {
2479                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2480                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2481                         }
2482                         else
2483                                 GL_AlphaToCoverage(false);
2484                 }
2485         }
2486         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2487                 colormod = dummy_colormod;
2488         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2489                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2490         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2491                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2492         switch(vid.renderpath)
2493         {
2494         case RENDERPATH_D3D9:
2495 #ifdef SUPPORTD3D
2496                 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2497                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2498                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2499                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2500                 if (mode == SHADERMODE_LIGHTSOURCE)
2501                 {
2502                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2503                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2504                 }
2505                 else
2506                 {
2507                         if (mode == SHADERMODE_LIGHTDIRECTION)
2508                         {
2509                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2510                         }
2511                 }
2512                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2513                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2514                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2515                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2516                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2517
2518                 if (mode == SHADERMODE_LIGHTSOURCE)
2519                 {
2520                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2521                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2522                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2524                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2525
2526                         // additive passes are only darkened by fog, not tinted
2527                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2528                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2529                 }
2530                 else
2531                 {
2532                         if (mode == SHADERMODE_FLATCOLOR)
2533                         {
2534                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2535                         }
2536                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2537                         {
2538                                 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]);
2539                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2540                                 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);
2541                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2542                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2543                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2544                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2545                         }
2546                         else
2547                         {
2548                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2549                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2550                                 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);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2553                         }
2554                         // additive passes are only darkened by fog, not tinted
2555                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2557                         else
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2559                         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);
2560                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2561                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2562                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2563                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2564                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2565                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2566                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2567                         if (mode == SHADERMODE_WATER)
2568                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2569                 }
2570                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2571                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2572                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2573                 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));
2574                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2575                 if (rsurface.texture->pantstexture)
2576                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2577                 else
2578                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2579                 if (rsurface.texture->shirttexture)
2580                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2581                 else
2582                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2583                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2584                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2585                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2586                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2587                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2588                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2589                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2590                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2591                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2592                         );
2593                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2594                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2595                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2596                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2597
2598                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2599                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2600                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2601                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2602                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2603                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2604                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2605                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2606                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2607                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2608                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2609                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2610                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2611                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2612                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2613                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2614                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2615                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2616                 {
2617                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2618                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2619                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2620                 }
2621                 else
2622                 {
2623                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2624                 }
2625 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2626                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2627                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2628                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2629                 {
2630                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2631                         if (rsurface.rtlight)
2632                         {
2633                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2634                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2635                         }
2636                 }
2637 #endif
2638                 break;
2639         case RENDERPATH_D3D10:
2640                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2641                 break;
2642         case RENDERPATH_D3D11:
2643                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2644                 break;
2645         case RENDERPATH_GL20:
2646         case RENDERPATH_GLES2:
2647                 if (!vid.useinterleavedarrays)
2648                 {
2649                         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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2650                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2651                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2652                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2653                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2654                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2655                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2656                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2657                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2658                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2659                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2660                 }
2661                 else
2662                 {
2663                         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) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2664                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2665                 }
2666                 // this has to be after RSurf_PrepareVerticesForBatch
2667                 if (rsurface.batchskeletaltransform3x4)
2668                         permutation |= SHADERPERMUTATION_SKELETAL;
2669                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2670                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2671                 if (mode == SHADERMODE_LIGHTSOURCE)
2672                 {
2673                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2674                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2675                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2676                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2677                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2678                         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);
2679         
2680                         // additive passes are only darkened by fog, not tinted
2681                         if (r_glsl_permutation->loc_FogColor >= 0)
2682                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2683                         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);
2684                 }
2685                 else
2686                 {
2687                         if (mode == SHADERMODE_FLATCOLOR)
2688                         {
2689                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2690                         }
2691                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2692                         {
2693                                 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]);
2694                                 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]);
2695                                 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);
2696                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2697                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2698                                 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]);
2699                                 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]);
2700                         }
2701                         else
2702                         {
2703                                 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]);
2704                                 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]);
2705                                 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);
2706                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2707                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2708                         }
2709                         // additive passes are only darkened by fog, not tinted
2710                         if (r_glsl_permutation->loc_FogColor >= 0)
2711                         {
2712                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2713                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2714                                 else
2715                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2716                         }
2717                         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);
2718                         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]);
2719                         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]);
2720                         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]);
2721                         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]);
2722                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2723                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2724                         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);
2725                         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]);
2726                 }
2727                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2728                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2729                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2730                 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]);
2731                 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]);
2732
2733                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2734                 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));
2735                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2736                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2737                 {
2738                         if (rsurface.texture->pantstexture)
2739                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2740                         else
2741                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2742                 }
2743                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2744                 {
2745                         if (rsurface.texture->shirttexture)
2746                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2747                         else
2748                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2749                 }
2750                 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]);
2751                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2752                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2753                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2754                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2755                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2756                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2757                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2758                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2759                         );
2760                 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);
2761                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2762                 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]);
2763                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2764                 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);}
2765                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2766
2767                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2768                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2769                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2770                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2771                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2772                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2773                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2774                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2775                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2776                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2777                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2778                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2779                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2780                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2781                 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);
2782                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2783                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2784                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2785                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2786                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2787                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2788                 {
2789                         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);
2790                         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);
2791                         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);
2792                 }
2793                 else
2794                 {
2795                         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);
2796                 }
2797                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2798                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2799                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2800                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2801                 {
2802                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2803                         if (rsurface.rtlight)
2804                         {
2805                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2806                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2807                         }
2808                 }
2809                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2810                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2811                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2812                 CHECKGLERROR
2813                 break;
2814         case RENDERPATH_GL11:
2815         case RENDERPATH_GL13:
2816         case RENDERPATH_GLES1:
2817                 break;
2818         case RENDERPATH_SOFT:
2819                 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2820                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2821                 R_SetupShader_SetPermutationSoft(mode, permutation);
2822                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2823                 if (mode == SHADERMODE_LIGHTSOURCE)
2824                 {
2825                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2826                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2827                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2828                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2831         
2832                         // additive passes are only darkened by fog, not tinted
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2834                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2835                 }
2836                 else
2837                 {
2838                         if (mode == SHADERMODE_FLATCOLOR)
2839                         {
2840                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2841                         }
2842                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2843                         {
2844                                 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]);
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2846                                 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);
2847                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2849                                 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]);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2851                         }
2852                         else
2853                         {
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2856                                 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);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2859                         }
2860                         // additive passes are only darkened by fog, not tinted
2861                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2863                         else
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2865                         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);
2866                         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]);
2867                         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]);
2868                         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]);
2869                         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]);
2870                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2871                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2872                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2873                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2874                 }
2875                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2876                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2877                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2878                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2879                 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]);
2880
2881                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2882                 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));
2883                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2884                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2885                 {
2886                         if (rsurface.texture->pantstexture)
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2888                         else
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2890                 }
2891                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2892                 {
2893                         if (rsurface.texture->shirttexture)
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2895                         else
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2897                 }
2898                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2899                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2900                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2901                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2902                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2903                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2904                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2905                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2907                         );
2908                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2909                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2910                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2911                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2912
2913                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2914                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2915                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2916                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2917                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2918                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2919                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2920                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2921                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2922                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2923                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2924                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2925                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2926                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2927                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2928                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2929                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2930                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2931                 {
2932                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2933                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2934                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2935                 }
2936                 else
2937                 {
2938                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2939                 }
2940 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2941                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2942                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2943                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2944                 {
2945                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2946                         if (rsurface.rtlight)
2947                         {
2948                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2949                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2950                         }
2951                 }
2952                 break;
2953         }
2954 }
2955
2956 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2957 {
2958         // select a permutation of the lighting shader appropriate to this
2959         // combination of texture, entity, light source, and fogging, only use the
2960         // minimum features necessary to avoid wasting rendering time in the
2961         // fragment shader on features that are not being used
2962         unsigned int permutation = 0;
2963         unsigned int mode = 0;
2964         const float *lightcolorbase = rtlight->currentcolor;
2965         float ambientscale = rtlight->ambientscale;
2966         float diffusescale = rtlight->diffusescale;
2967         float specularscale = rtlight->specularscale;
2968         // this is the location of the light in view space
2969         vec3_t viewlightorigin;
2970         // this transforms from view space (camera) to light space (cubemap)
2971         matrix4x4_t viewtolight;
2972         matrix4x4_t lighttoview;
2973         float viewtolight16f[16];
2974         // light source
2975         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2976         if (rtlight->currentcubemap != r_texture_whitecube)
2977                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2978         if (diffusescale > 0)
2979                 permutation |= SHADERPERMUTATION_DIFFUSE;
2980         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2981                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2982         if (r_shadow_usingshadowmap2d)
2983         {
2984                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2985                 if (r_shadow_shadowmapvsdct)
2986                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2987
2988                 if (r_shadow_shadowmap2ddepthbuffer)
2989                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2990         }
2991         if (vid.allowalphatocoverage)
2992                 GL_AlphaToCoverage(false);
2993         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2994         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2995         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2996         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2997         switch(vid.renderpath)
2998         {
2999         case RENDERPATH_D3D9:
3000 #ifdef SUPPORTD3D
3001                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3002                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3003                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3004                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3005                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3006                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3007                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3008                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3009                 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);
3010                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3011                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3012
3013                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3014                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3015                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3016                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3017                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3018 #endif
3019                 break;
3020         case RENDERPATH_D3D10:
3021                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3022                 break;
3023         case RENDERPATH_D3D11:
3024                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3025                 break;
3026         case RENDERPATH_GL20:
3027         case RENDERPATH_GLES2:
3028                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3029                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3030                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3031                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3032                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3033                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3034                 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]);
3035                 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]);
3036                 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);
3037                 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]);
3038                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3039
3040                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3041                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3042                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3043                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3044                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3045                 break;
3046         case RENDERPATH_GL11:
3047         case RENDERPATH_GL13:
3048         case RENDERPATH_GLES1:
3049                 break;
3050         case RENDERPATH_SOFT:
3051                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3052                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3053                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3054                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3055                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3056                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3057                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3058                 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]);
3059                 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);
3060                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3061                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3062
3063                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3064                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3065                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3066                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3067                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3068                 break;
3069         }
3070 }
3071
3072 #define SKINFRAME_HASH 1024
3073
3074 typedef struct
3075 {
3076         int loadsequence; // incremented each level change
3077         memexpandablearray_t array;
3078         skinframe_t *hash[SKINFRAME_HASH];
3079 }
3080 r_skinframe_t;
3081 r_skinframe_t r_skinframe;
3082
3083 void R_SkinFrame_PrepareForPurge(void)
3084 {
3085         r_skinframe.loadsequence++;
3086         // wrap it without hitting zero
3087         if (r_skinframe.loadsequence >= 200)
3088                 r_skinframe.loadsequence = 1;
3089 }
3090
3091 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3092 {
3093         if (!skinframe)
3094                 return;
3095         // mark the skinframe as used for the purging code
3096         skinframe->loadsequence = r_skinframe.loadsequence;
3097 }
3098
3099 void R_SkinFrame_Purge(void)
3100 {
3101         int i;
3102         skinframe_t *s;
3103         for (i = 0;i < SKINFRAME_HASH;i++)
3104         {
3105                 for (s = r_skinframe.hash[i];s;s = s->next)
3106                 {
3107                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3108                         {
3109                                 if (s->merged == s->base)
3110                                         s->merged = NULL;
3111                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3112                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3113                                 R_PurgeTexture(s->merged);s->merged = NULL;
3114                                 R_PurgeTexture(s->base  );s->base   = NULL;
3115                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3116                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3117                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3118                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3119                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3120                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3121                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3122                                 s->loadsequence = 0;
3123                         }
3124                 }
3125         }
3126 }
3127
3128 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3129         skinframe_t *item;
3130         char basename[MAX_QPATH];
3131
3132         Image_StripImageExtension(name, basename, sizeof(basename));
3133
3134         if( last == NULL ) {
3135                 int hashindex;
3136                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3137                 item = r_skinframe.hash[hashindex];
3138         } else {
3139                 item = last->next;
3140         }
3141
3142         // linearly search through the hash bucket
3143         for( ; item ; item = item->next ) {
3144                 if( !strcmp( item->basename, basename ) ) {
3145                         return item;
3146                 }
3147         }
3148         return NULL;
3149 }
3150
3151 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3152 {
3153         skinframe_t *item;
3154         int hashindex;
3155         char basename[MAX_QPATH];
3156
3157         Image_StripImageExtension(name, basename, sizeof(basename));
3158
3159         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3160         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3161                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3162                         break;
3163
3164         if (!item) {
3165                 rtexture_t *dyntexture;
3166                 // check whether its a dynamic texture
3167                 dyntexture = CL_GetDynTexture( basename );
3168                 if (!add && !dyntexture)
3169                         return NULL;
3170                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3171                 memset(item, 0, sizeof(*item));
3172                 strlcpy(item->basename, basename, sizeof(item->basename));
3173                 item->base = dyntexture; // either NULL or dyntexture handle
3174                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3175                 item->comparewidth = comparewidth;
3176                 item->compareheight = compareheight;
3177                 item->comparecrc = comparecrc;
3178                 item->next = r_skinframe.hash[hashindex];
3179                 r_skinframe.hash[hashindex] = item;
3180         }
3181         else if (textureflags & TEXF_FORCE_RELOAD)
3182         {
3183                 rtexture_t *dyntexture;
3184                 // check whether its a dynamic texture
3185                 dyntexture = CL_GetDynTexture( basename );
3186                 if (!add && !dyntexture)
3187                         return NULL;
3188                 if (item->merged == item->base)
3189                         item->merged = NULL;
3190                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3191                 R_PurgeTexture(item->stain );item->stain  = NULL;
3192                 R_PurgeTexture(item->merged);item->merged = NULL;
3193                 R_PurgeTexture(item->base  );item->base   = NULL;
3194                 R_PurgeTexture(item->pants );item->pants  = NULL;
3195                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3196                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3197                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3198                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3199                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3200         R_PurgeTexture(item->reflect);item->reflect = NULL;
3201                 item->loadsequence = 0;
3202         }
3203         else if( item->base == NULL )
3204         {
3205                 rtexture_t *dyntexture;
3206                 // check whether its a dynamic texture
3207                 // 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]
3208                 dyntexture = CL_GetDynTexture( basename );
3209                 item->base = dyntexture; // either NULL or dyntexture handle
3210         }
3211
3212         R_SkinFrame_MarkUsed(item);
3213         return item;
3214 }
3215
3216 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3217         { \
3218                 unsigned long long avgcolor[5], wsum; \
3219                 int pix, comp, w; \
3220                 avgcolor[0] = 0; \
3221                 avgcolor[1] = 0; \
3222                 avgcolor[2] = 0; \
3223                 avgcolor[3] = 0; \
3224                 avgcolor[4] = 0; \
3225                 wsum = 0; \
3226                 for(pix = 0; pix < cnt; ++pix) \
3227                 { \
3228                         w = 0; \
3229                         for(comp = 0; comp < 3; ++comp) \
3230                                 w += getpixel; \
3231                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3232                         { \
3233                                 ++wsum; \
3234                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3235                                 w = getpixel; \
3236                                 for(comp = 0; comp < 3; ++comp) \
3237                                         avgcolor[comp] += getpixel * w; \
3238                                 avgcolor[3] += w; \
3239                         } \
3240                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3241                         avgcolor[4] += getpixel; \
3242                 } \
3243                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3244                         avgcolor[3] = 1; \
3245                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3246                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3247                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3248                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3249         }
3250
3251 extern cvar_t gl_picmip;
3252 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3253 {
3254         int j;
3255         unsigned char *pixels;
3256         unsigned char *bumppixels;
3257         unsigned char *basepixels = NULL;
3258         int basepixels_width = 0;
3259         int basepixels_height = 0;
3260         skinframe_t *skinframe;
3261         rtexture_t *ddsbase = NULL;
3262         qboolean ddshasalpha = false;
3263         float ddsavgcolor[4];
3264         char basename[MAX_QPATH];
3265         int miplevel = R_PicmipForFlags(textureflags);
3266         int savemiplevel = miplevel;
3267         int mymiplevel;
3268         char vabuf[1024];
3269
3270         if (cls.state == ca_dedicated)
3271                 return NULL;
3272
3273         // return an existing skinframe if already loaded
3274         // if loading of the first image fails, don't make a new skinframe as it
3275         // would cause all future lookups of this to be missing
3276         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3277         if (skinframe && skinframe->base)
3278                 return skinframe;
3279
3280         Image_StripImageExtension(name, basename, sizeof(basename));
3281
3282         // check for DDS texture file first
3283         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3284         {
3285                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3286                 if (basepixels == NULL)
3287                         return NULL;
3288         }
3289
3290         // FIXME handle miplevel
3291
3292         if (developer_loading.integer)
3293                 Con_Printf("loading skin \"%s\"\n", name);
3294
3295         // we've got some pixels to store, so really allocate this new texture now
3296         if (!skinframe)
3297                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3298         textureflags &= ~TEXF_FORCE_RELOAD;
3299         skinframe->stain = NULL;
3300         skinframe->merged = NULL;
3301         skinframe->base = NULL;
3302         skinframe->pants = NULL;
3303         skinframe->shirt = NULL;
3304         skinframe->nmap = NULL;
3305         skinframe->gloss = NULL;
3306         skinframe->glow = NULL;
3307         skinframe->fog = NULL;
3308         skinframe->reflect = NULL;
3309         skinframe->hasalpha = false;
3310
3311         if (ddsbase)
3312         {
3313                 skinframe->base = ddsbase;
3314                 skinframe->hasalpha = ddshasalpha;
3315                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3316                 if (r_loadfog && skinframe->hasalpha)
3317                         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);
3318                 //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]);
3319         }
3320         else
3321         {
3322                 basepixels_width = image_width;
3323                 basepixels_height = image_height;
3324                 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);
3325                 if (textureflags & TEXF_ALPHA)
3326                 {
3327                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3328                         {
3329                                 if (basepixels[j] < 255)
3330                                 {
3331                                         skinframe->hasalpha = true;
3332                                         break;
3333                                 }
3334                         }
3335                         if (r_loadfog && skinframe->hasalpha)
3336                         {
3337                                 // has transparent pixels
3338                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3339                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3340                                 {
3341                                         pixels[j+0] = 255;
3342                                         pixels[j+1] = 255;
3343                                         pixels[j+2] = 255;
3344                                         pixels[j+3] = basepixels[j+3];
3345                                 }
3346                                 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);
3347                                 Mem_Free(pixels);
3348                         }
3349                 }
3350                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3351 #ifndef USE_GLES2
3352                 //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]);
3353                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3354                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3355                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3356                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3357 #endif
3358         }
3359
3360         if (r_loaddds)
3361         {
3362                 mymiplevel = savemiplevel;
3363                 if (r_loadnormalmap)
3364                         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);
3365                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3366                 if (r_loadgloss)
3367                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3368                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3369                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3370                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3371         }
3372
3373         // _norm is the name used by tenebrae and has been adopted as standard
3374         if (r_loadnormalmap && skinframe->nmap == NULL)
3375         {
3376                 mymiplevel = savemiplevel;
3377                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3378                 {
3379                         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);
3380                         Mem_Free(pixels);
3381                         pixels = NULL;
3382                 }
3383                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3384                 {
3385                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3386                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3387                         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);
3388                         Mem_Free(pixels);
3389                         Mem_Free(bumppixels);
3390                 }
3391                 else if (r_shadow_bumpscale_basetexture.value > 0)
3392                 {
3393                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3394                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3395                         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);
3396                         Mem_Free(pixels);
3397                 }
3398 #ifndef USE_GLES2
3399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3400                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401 #endif
3402         }
3403
3404         // _luma is supported only for tenebrae compatibility
3405         // _glow is the preferred name
3406         mymiplevel = savemiplevel;
3407         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))))
3408         {
3409                 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);
3410 #ifndef USE_GLES2
3411                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3412                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3413 #endif
3414                 Mem_Free(pixels);pixels = NULL;
3415         }
3416
3417         mymiplevel = savemiplevel;
3418         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3419         {
3420                 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);
3421 #ifndef USE_GLES2
3422                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3423                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3424 #endif
3425                 Mem_Free(pixels);
3426                 pixels = NULL;
3427         }
3428
3429         mymiplevel = savemiplevel;
3430         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3431         {
3432                 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);
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3435                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3436 #endif
3437                 Mem_Free(pixels);
3438                 pixels = NULL;
3439         }
3440
3441         mymiplevel = savemiplevel;
3442         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3443         {
3444                 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);
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3447                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3448 #endif
3449                 Mem_Free(pixels);
3450                 pixels = NULL;
3451         }
3452
3453         mymiplevel = savemiplevel;
3454         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3455         {
3456                 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);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3459                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3460 #endif
3461                 Mem_Free(pixels);
3462                 pixels = NULL;
3463         }
3464
3465         if (basepixels)
3466                 Mem_Free(basepixels);
3467
3468         return skinframe;
3469 }
3470
3471 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3472 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3473 {
3474         int i;
3475         unsigned char *temp1, *temp2;
3476         skinframe_t *skinframe;
3477         char vabuf[1024];
3478
3479         if (cls.state == ca_dedicated)
3480                 return NULL;
3481
3482         // if already loaded just return it, otherwise make a new skinframe
3483         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3484         if (skinframe->base)
3485                 return skinframe;
3486         textureflags &= ~TEXF_FORCE_RELOAD;
3487
3488         skinframe->stain = NULL;
3489         skinframe->merged = NULL;
3490         skinframe->base = NULL;
3491         skinframe->pants = NULL;
3492         skinframe->shirt = NULL;
3493         skinframe->nmap = NULL;
3494         skinframe->gloss = NULL;
3495         skinframe->glow = NULL;
3496         skinframe->fog = NULL;
3497         skinframe->reflect = NULL;
3498         skinframe->hasalpha = false;
3499
3500         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3501         if (!skindata)
3502                 return NULL;
3503
3504         if (developer_loading.integer)
3505                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3506
3507         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3508         {
3509                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3510                 temp2 = temp1 + width * height * 4;
3511                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3512                 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);
3513                 Mem_Free(temp1);
3514         }
3515         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3516         if (textureflags & TEXF_ALPHA)
3517         {
3518                 for (i = 3;i < width * height * 4;i += 4)
3519                 {
3520                         if (skindata[i] < 255)
3521                         {
3522                                 skinframe->hasalpha = true;
3523                                 break;
3524                         }
3525                 }
3526                 if (r_loadfog && skinframe->hasalpha)
3527                 {
3528                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3529                         memcpy(fogpixels, skindata, width * height * 4);
3530                         for (i = 0;i < width * height * 4;i += 4)
3531                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3532                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3533                         Mem_Free(fogpixels);
3534                 }
3535         }
3536
3537         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3538         //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]);
3539
3540         return skinframe;
3541 }
3542
3543 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3544 {
3545         int i;
3546         int featuresmask;
3547         skinframe_t *skinframe;
3548
3549         if (cls.state == ca_dedicated)
3550                 return NULL;
3551
3552         // if already loaded just return it, otherwise make a new skinframe
3553         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3554         if (skinframe->base)
3555                 return skinframe;
3556         //textureflags &= ~TEXF_FORCE_RELOAD;
3557
3558         skinframe->stain = NULL;
3559         skinframe->merged = NULL;
3560         skinframe->base = NULL;
3561         skinframe->pants = NULL;
3562         skinframe->shirt = NULL;
3563         skinframe->nmap = NULL;
3564         skinframe->gloss = NULL;
3565         skinframe->glow = NULL;
3566         skinframe->fog = NULL;
3567         skinframe->reflect = NULL;
3568         skinframe->hasalpha = false;
3569
3570         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3571         if (!skindata)
3572                 return NULL;
3573
3574         if (developer_loading.integer)
3575                 Con_Printf("loading quake skin \"%s\"\n", name);
3576
3577         // 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)
3578         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3579         memcpy(skinframe->qpixels, skindata, width*height);
3580         skinframe->qwidth = width;
3581         skinframe->qheight = height;
3582
3583         featuresmask = 0;
3584         for (i = 0;i < width * height;i++)
3585                 featuresmask |= palette_featureflags[skindata[i]];
3586
3587         skinframe->hasalpha = false;
3588         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3589         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3590         skinframe->qgeneratemerged = true;
3591         skinframe->qgeneratebase = skinframe->qhascolormapping;
3592         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3593
3594         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3595         //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]);
3596
3597         return skinframe;
3598 }
3599
3600 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3601 {
3602         int width;
3603         int height;
3604         unsigned char *skindata;
3605         char vabuf[1024];
3606
3607         if (!skinframe->qpixels)
3608                 return;
3609
3610         if (!skinframe->qhascolormapping)
3611                 colormapped = false;
3612
3613         if (colormapped)
3614         {
3615                 if (!skinframe->qgeneratebase)
3616                         return;
3617         }
3618         else
3619         {
3620                 if (!skinframe->qgeneratemerged)
3621                         return;
3622         }
3623
3624         width = skinframe->qwidth;
3625         height = skinframe->qheight;
3626         skindata = skinframe->qpixels;
3627
3628         if (skinframe->qgeneratenmap)
3629         {
3630                 unsigned char *temp1, *temp2;
3631                 skinframe->qgeneratenmap = false;
3632                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3633                 temp2 = temp1 + width * height * 4;
3634                 // use either a custom palette or the quake palette
3635                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3636                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3637                 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);
3638                 Mem_Free(temp1);
3639         }
3640
3641         if (skinframe->qgenerateglow)
3642         {
3643                 skinframe->qgenerateglow = false;
3644                 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
3645         }
3646
3647         if (colormapped)
3648         {
3649                 skinframe->qgeneratebase = false;
3650                 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);
3651                 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);
3652                 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);
3653         }
3654         else
3655         {
3656                 skinframe->qgeneratemerged = false;
3657                 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);
3658         }
3659
3660         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3661         {
3662                 Mem_Free(skinframe->qpixels);
3663                 skinframe->qpixels = NULL;
3664         }
3665 }
3666
3667 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)
3668 {
3669         int i;
3670         skinframe_t *skinframe;
3671         char vabuf[1024];
3672
3673         if (cls.state == ca_dedicated)
3674                 return NULL;
3675
3676         // if already loaded just return it, otherwise make a new skinframe
3677         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3678         if (skinframe->base)
3679                 return skinframe;
3680         textureflags &= ~TEXF_FORCE_RELOAD;
3681
3682         skinframe->stain = NULL;
3683         skinframe->merged = NULL;
3684         skinframe->base = NULL;
3685         skinframe->pants = NULL;
3686         skinframe->shirt = NULL;
3687         skinframe->nmap = NULL;
3688         skinframe->gloss = NULL;
3689         skinframe->glow = NULL;
3690         skinframe->fog = NULL;
3691         skinframe->reflect = NULL;
3692         skinframe->hasalpha = false;
3693
3694         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3695         if (!skindata)
3696                 return NULL;
3697
3698         if (developer_loading.integer)
3699                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3700
3701         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3702         if (textureflags & TEXF_ALPHA)
3703         {
3704                 for (i = 0;i < width * height;i++)
3705                 {
3706                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3707                         {
3708                                 skinframe->hasalpha = true;
3709                                 break;
3710                         }
3711                 }
3712                 if (r_loadfog && skinframe->hasalpha)
3713                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3714         }
3715
3716         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3717         //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]);
3718
3719         return skinframe;
3720 }
3721
3722 skinframe_t *R_SkinFrame_LoadMissing(void)
3723 {
3724         skinframe_t *skinframe;
3725
3726         if (cls.state == ca_dedicated)
3727                 return NULL;
3728
3729         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3730         skinframe->stain = NULL;
3731         skinframe->merged = NULL;
3732         skinframe->base = NULL;
3733         skinframe->pants = NULL;
3734         skinframe->shirt = NULL;
3735         skinframe->nmap = NULL;
3736         skinframe->gloss = NULL;
3737         skinframe->glow = NULL;
3738         skinframe->fog = NULL;
3739         skinframe->reflect = NULL;
3740         skinframe->hasalpha = false;
3741
3742         skinframe->avgcolor[0] = rand() / RAND_MAX;
3743         skinframe->avgcolor[1] = rand() / RAND_MAX;
3744         skinframe->avgcolor[2] = rand() / RAND_MAX;
3745         skinframe->avgcolor[3] = 1;
3746
3747         return skinframe;
3748 }
3749
3750 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3751 typedef struct suffixinfo_s
3752 {
3753         const char *suffix;
3754         qboolean flipx, flipy, flipdiagonal;
3755 }
3756 suffixinfo_t;
3757 static suffixinfo_t suffix[3][6] =
3758 {
3759         {
3760                 {"px",   false, false, false},
3761                 {"nx",   false, false, false},
3762                 {"py",   false, false, false},
3763                 {"ny",   false, false, false},
3764                 {"pz",   false, false, false},
3765                 {"nz",   false, false, false}
3766         },
3767         {
3768                 {"posx", false, false, false},
3769                 {"negx", false, false, false},
3770                 {"posy", false, false, false},
3771                 {"negy", false, false, false},
3772                 {"posz", false, false, false},
3773                 {"negz", false, false, false}
3774         },
3775         {
3776                 {"rt",    true, false,  true},
3777                 {"lf",   false,  true,  true},
3778                 {"ft",    true,  true, false},
3779                 {"bk",   false, false, false},
3780                 {"up",    true, false,  true},
3781                 {"dn",    true, false,  true}
3782         }
3783 };
3784
3785 static int componentorder[4] = {0, 1, 2, 3};
3786
3787 static rtexture_t *R_LoadCubemap(const char *basename)
3788 {
3789         int i, j, cubemapsize;
3790         unsigned char *cubemappixels, *image_buffer;
3791         rtexture_t *cubemaptexture;
3792         char name[256];
3793         // must start 0 so the first loadimagepixels has no requested width/height
3794         cubemapsize = 0;
3795         cubemappixels = NULL;
3796         cubemaptexture = NULL;
3797         // keep trying different suffix groups (posx, px, rt) until one loads
3798         for (j = 0;j < 3 && !cubemappixels;j++)
3799         {
3800                 // load the 6 images in the suffix group
3801                 for (i = 0;i < 6;i++)
3802                 {
3803                         // generate an image name based on the base and and suffix
3804                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3805                         // load it
3806                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3807                         {
3808                                 // an image loaded, make sure width and height are equal
3809                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3810                                 {
3811                                         // if this is the first image to load successfully, allocate the cubemap memory
3812                                         if (!cubemappixels && image_width >= 1)
3813                                         {
3814                                                 cubemapsize = image_width;
3815                                                 // note this clears to black, so unavailable sides are black
3816                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3817                                         }
3818                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3819                                         if (cubemappixels)
3820                                                 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);
3821                                 }
3822                                 else
3823                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3824                                 // free the image
3825                                 Mem_Free(image_buffer);
3826                         }
3827                 }
3828         }
3829         // if a cubemap loaded, upload it
3830         if (cubemappixels)
3831         {
3832                 if (developer_loading.integer)
3833                         Con_Printf("loading cubemap \"%s\"\n", basename);
3834
3835                 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);
3836                 Mem_Free(cubemappixels);
3837         }
3838         else
3839         {
3840                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3841                 if (developer_loading.integer)
3842                 {
3843                         Con_Printf("(tried tried images ");
3844                         for (j = 0;j < 3;j++)
3845                                 for (i = 0;i < 6;i++)
3846                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3847                         Con_Print(" and was unable to find any of them).\n");
3848                 }
3849         }
3850         return cubemaptexture;
3851 }
3852
3853 rtexture_t *R_GetCubemap(const char *basename)
3854 {
3855         int i;
3856         for (i = 0;i < r_texture_numcubemaps;i++)
3857                 if (r_texture_cubemaps[i] != NULL)
3858                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3859                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3860         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3861                 return r_texture_whitecube;
3862         r_texture_numcubemaps++;
3863         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3864         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3865         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3866         return r_texture_cubemaps[i]->texture;
3867 }
3868
3869 static void R_Main_FreeViewCache(void)
3870 {
3871         if (r_refdef.viewcache.entityvisible)
3872                 Mem_Free(r_refdef.viewcache.entityvisible);
3873         if (r_refdef.viewcache.world_pvsbits)
3874                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3875         if (r_refdef.viewcache.world_leafvisible)
3876                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3877         if (r_refdef.viewcache.world_surfacevisible)
3878                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3879         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3880 }
3881
3882 static void R_Main_ResizeViewCache(void)
3883 {
3884         int numentities = r_refdef.scene.numentities;
3885         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3886         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3887         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3888         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3889         if (r_refdef.viewcache.maxentities < numentities)
3890         {
3891                 r_refdef.viewcache.maxentities = numentities;
3892                 if (r_refdef.viewcache.entityvisible)
3893                         Mem_Free(r_refdef.viewcache.entityvisible);
3894                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3895         }
3896         if (r_refdef.viewcache.world_numclusters != numclusters)
3897         {
3898                 r_refdef.viewcache.world_numclusters = numclusters;
3899                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3900                 if (r_refdef.viewcache.world_pvsbits)
3901                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3902                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3903         }
3904         if (r_refdef.viewcache.world_numleafs != numleafs)
3905         {
3906                 r_refdef.viewcache.world_numleafs = numleafs;
3907                 if (r_refdef.viewcache.world_leafvisible)
3908                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3909                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3910         }
3911         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3912         {
3913                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3914                 if (r_refdef.viewcache.world_surfacevisible)
3915                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3916                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3917         }
3918 }
3919
3920 extern rtexture_t *loadingscreentexture;
3921 static void gl_main_start(void)
3922 {
3923         loadingscreentexture = NULL;
3924         r_texture_blanknormalmap = NULL;
3925         r_texture_white = NULL;
3926         r_texture_grey128 = NULL;
3927         r_texture_black = NULL;
3928         r_texture_whitecube = NULL;
3929         r_texture_normalizationcube = NULL;
3930         r_texture_fogattenuation = NULL;
3931         r_texture_fogheighttexture = NULL;
3932         r_texture_gammaramps = NULL;
3933         r_texture_numcubemaps = 0;
3934
3935         r_loaddds = r_texture_dds_load.integer != 0;
3936         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3937
3938         switch(vid.renderpath)
3939         {
3940         case RENDERPATH_GL20:
3941         case RENDERPATH_D3D9:
3942         case RENDERPATH_D3D10:
3943         case RENDERPATH_D3D11:
3944         case RENDERPATH_SOFT:
3945         case RENDERPATH_GLES2:
3946                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3947                 Cvar_SetValueQuick(&gl_combine, 1);
3948                 Cvar_SetValueQuick(&r_glsl, 1);
3949                 r_loadnormalmap = true;
3950                 r_loadgloss = true;
3951                 r_loadfog = false;
3952                 break;
3953         case RENDERPATH_GL13:
3954         case RENDERPATH_GLES1:
3955                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3956                 Cvar_SetValueQuick(&gl_combine, 1);
3957                 Cvar_SetValueQuick(&r_glsl, 0);
3958                 r_loadnormalmap = false;
3959                 r_loadgloss = false;
3960                 r_loadfog = true;
3961                 break;
3962         case RENDERPATH_GL11:
3963                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3964                 Cvar_SetValueQuick(&gl_combine, 0);
3965                 Cvar_SetValueQuick(&r_glsl, 0);
3966                 r_loadnormalmap = false;
3967                 r_loadgloss = false;
3968                 r_loadfog = true;
3969                 break;
3970         }
3971
3972         R_AnimCache_Free();
3973         R_FrameData_Reset();
3974
3975         r_numqueries = 0;
3976         r_maxqueries = 0;
3977         memset(r_queries, 0, sizeof(r_queries));
3978
3979         r_qwskincache = NULL;
3980         r_qwskincache_size = 0;
3981
3982         // due to caching of texture_t references, the collision cache must be reset
3983         Collision_Cache_Reset(true);
3984
3985         // set up r_skinframe loading system for textures
3986         memset(&r_skinframe, 0, sizeof(r_skinframe));
3987         r_skinframe.loadsequence = 1;
3988         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3989
3990         r_main_texturepool = R_AllocTexturePool();
3991         R_BuildBlankTextures();
3992         R_BuildNoTexture();
3993         if (vid.support.arb_texture_cube_map)
3994         {
3995                 R_BuildWhiteCube();
3996                 R_BuildNormalizationCube();
3997         }
3998         r_texture_fogattenuation = NULL;
3999         r_texture_fogheighttexture = NULL;
4000         r_texture_gammaramps = NULL;
4001         //r_texture_fogintensity = NULL;
4002         memset(&r_fb, 0, sizeof(r_fb));
4003         r_glsl_permutation = NULL;
4004         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4005         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4006         glslshaderstring = NULL;
4007 #ifdef SUPPORTD3D
4008         r_hlsl_permutation = NULL;
4009         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4010         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4011 #endif
4012         hlslshaderstring = NULL;
4013         memset(&r_svbsp, 0, sizeof (r_svbsp));
4014
4015         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4016         r_texture_numcubemaps = 0;
4017
4018         r_refdef.fogmasktable_density = 0;
4019 }
4020
4021 static void gl_main_shutdown(void)
4022 {
4023         R_AnimCache_Free();
4024         R_FrameData_Reset();
4025
4026         R_Main_FreeViewCache();
4027
4028         switch(vid.renderpath)
4029         {
4030         case RENDERPATH_GL11:
4031         case RENDERPATH_GL13:
4032         case RENDERPATH_GL20:
4033         case RENDERPATH_GLES1:
4034         case RENDERPATH_GLES2:
4035 #ifdef GL_SAMPLES_PASSED_ARB
4036                 if (r_maxqueries)
4037                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4038 #endif
4039                 break;
4040         case RENDERPATH_D3D9:
4041                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4042                 break;
4043         case RENDERPATH_D3D10:
4044                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4045                 break;
4046         case RENDERPATH_D3D11:
4047                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4048                 break;
4049         case RENDERPATH_SOFT:
4050                 break;
4051         }
4052
4053         r_numqueries = 0;
4054         r_maxqueries = 0;
4055         memset(r_queries, 0, sizeof(r_queries));
4056
4057         r_qwskincache = NULL;
4058         r_qwskincache_size = 0;
4059
4060         // clear out the r_skinframe state
4061         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4062         memset(&r_skinframe, 0, sizeof(r_skinframe));
4063
4064         if (r_svbsp.nodes)
4065                 Mem_Free(r_svbsp.nodes);
4066         memset(&r_svbsp, 0, sizeof (r_svbsp));
4067         R_FreeTexturePool(&r_main_texturepool);
4068         loadingscreentexture = NULL;
4069         r_texture_blanknormalmap = NULL;
4070         r_texture_white = NULL;
4071         r_texture_grey128 = NULL;
4072         r_texture_black = NULL;
4073         r_texture_whitecube = NULL;
4074         r_texture_normalizationcube = NULL;
4075         r_texture_fogattenuation = NULL;
4076         r_texture_fogheighttexture = NULL;
4077         r_texture_gammaramps = NULL;
4078         r_texture_numcubemaps = 0;
4079         //r_texture_fogintensity = NULL;
4080         memset(&r_fb, 0, sizeof(r_fb));
4081         R_GLSL_Restart_f();
4082
4083         r_glsl_permutation = NULL;
4084         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4085         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4086         glslshaderstring = NULL;
4087 #ifdef SUPPORTD3D
4088         r_hlsl_permutation = NULL;
4089         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4090         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4091 #endif
4092         hlslshaderstring = NULL;
4093 }
4094
4095 static void gl_main_newmap(void)
4096 {
4097         // FIXME: move this code to client
4098         char *entities, entname[MAX_QPATH];
4099         if (r_qwskincache)
4100                 Mem_Free(r_qwskincache);
4101         r_qwskincache = NULL;
4102         r_qwskincache_size = 0;
4103         if (cl.worldmodel)
4104         {
4105                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4106                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4107                 {
4108                         CL_ParseEntityLump(entities);
4109                         Mem_Free(entities);
4110                         return;
4111                 }
4112                 if (cl.worldmodel->brush.entities)
4113                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4114         }
4115         R_Main_FreeViewCache();
4116
4117         R_FrameData_Reset();
4118 }
4119
4120 void GL_Main_Init(void)
4121 {
4122         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4123
4124         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4125         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4126         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4127         if (gamemode == GAME_NEHAHRA)
4128         {
4129                 Cvar_RegisterVariable (&gl_fogenable);
4130                 Cvar_RegisterVariable (&gl_fogdensity);
4131                 Cvar_RegisterVariable (&gl_fogred);
4132                 Cvar_RegisterVariable (&gl_foggreen);
4133                 Cvar_RegisterVariable (&gl_fogblue);
4134                 Cvar_RegisterVariable (&gl_fogstart);
4135                 Cvar_RegisterVariable (&gl_fogend);
4136                 Cvar_RegisterVariable (&gl_skyclip);
4137         }
4138         Cvar_RegisterVariable(&r_motionblur);
4139         Cvar_RegisterVariable(&r_damageblur);
4140         Cvar_RegisterVariable(&r_motionblur_averaging);
4141         Cvar_RegisterVariable(&r_motionblur_randomize);
4142         Cvar_RegisterVariable(&r_motionblur_minblur);
4143         Cvar_RegisterVariable(&r_motionblur_maxblur);
4144         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4145         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4146         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4147         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4148         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4149         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4150         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4151         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4152         Cvar_RegisterVariable(&r_equalize_entities_by);
4153         Cvar_RegisterVariable(&r_equalize_entities_to);
4154         Cvar_RegisterVariable(&r_depthfirst);
4155         Cvar_RegisterVariable(&r_useinfinitefarclip);
4156         Cvar_RegisterVariable(&r_farclip_base);
4157         Cvar_RegisterVariable(&r_farclip_world);
4158         Cvar_RegisterVariable(&r_nearclip);
4159         Cvar_RegisterVariable(&r_deformvertexes);
4160         Cvar_RegisterVariable(&r_transparent);
4161         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4162         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4163         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4164         Cvar_RegisterVariable(&r_showoverdraw);
4165         Cvar_RegisterVariable(&r_showbboxes);
4166         Cvar_RegisterVariable(&r_showsurfaces);
4167         Cvar_RegisterVariable(&r_showtris);
4168         Cvar_RegisterVariable(&r_shownormals);
4169         Cvar_RegisterVariable(&r_showlighting);
4170         Cvar_RegisterVariable(&r_showshadowvolumes);
4171         Cvar_RegisterVariable(&r_showcollisionbrushes);
4172         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4173         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4174         Cvar_RegisterVariable(&r_showdisabledepthtest);
4175         Cvar_RegisterVariable(&r_drawportals);
4176         Cvar_RegisterVariable(&r_drawentities);
4177         Cvar_RegisterVariable(&r_draw2d);
4178         Cvar_RegisterVariable(&r_drawworld);
4179         Cvar_RegisterVariable(&r_cullentities_trace);
4180         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4181         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4182         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4183         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4184         Cvar_RegisterVariable(&r_sortentities);
4185         Cvar_RegisterVariable(&r_drawviewmodel);
4186         Cvar_RegisterVariable(&r_drawexteriormodel);
4187         Cvar_RegisterVariable(&r_speeds);
4188         Cvar_RegisterVariable(&r_fullbrights);
4189         Cvar_RegisterVariable(&r_wateralpha);
4190         Cvar_RegisterVariable(&r_dynamic);
4191         Cvar_RegisterVariable(&r_fakelight);
4192         Cvar_RegisterVariable(&r_fakelight_intensity);
4193         Cvar_RegisterVariable(&r_fullbright);
4194         Cvar_RegisterVariable(&r_shadows);
4195         Cvar_RegisterVariable(&r_shadows_darken);
4196         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4197         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4198         Cvar_RegisterVariable(&r_shadows_throwdistance);
4199         Cvar_RegisterVariable(&r_shadows_throwdirection);
4200         Cvar_RegisterVariable(&r_shadows_focus);
4201         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4202         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4203         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4204         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4205         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4206         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4207         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4208         Cvar_RegisterVariable(&r_fog_exp2);
4209         Cvar_RegisterVariable(&r_fog_clear);
4210         Cvar_RegisterVariable(&r_drawfog);
4211         Cvar_RegisterVariable(&r_transparentdepthmasking);
4212         Cvar_RegisterVariable(&r_transparent_sortmindist);
4213         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4214         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4215         Cvar_RegisterVariable(&r_texture_dds_load);
4216         Cvar_RegisterVariable(&r_texture_dds_save);
4217         Cvar_RegisterVariable(&r_textureunits);
4218         Cvar_RegisterVariable(&gl_combine);
4219         Cvar_RegisterVariable(&r_usedepthtextures);
4220         Cvar_RegisterVariable(&r_viewfbo);
4221         Cvar_RegisterVariable(&r_viewscale);
4222         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4223         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4224         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4225         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4226         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4227         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4228         Cvar_RegisterVariable(&r_glsl);
4229         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4230         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4231         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4232         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4233         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4234         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4235         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4236         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4237         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4238         Cvar_RegisterVariable(&r_glsl_postprocess);
4239         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4240         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4241         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4242         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4243         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4244         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4245         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4246         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4247         Cvar_RegisterVariable(&r_celshading);
4248         Cvar_RegisterVariable(&r_celoutlines);
4249
4250         Cvar_RegisterVariable(&r_water);
4251         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4252         Cvar_RegisterVariable(&r_water_clippingplanebias);
4253         Cvar_RegisterVariable(&r_water_refractdistort);
4254         Cvar_RegisterVariable(&r_water_reflectdistort);
4255         Cvar_RegisterVariable(&r_water_scissormode);
4256         Cvar_RegisterVariable(&r_water_lowquality);
4257         Cvar_RegisterVariable(&r_water_hideplayer);
4258         Cvar_RegisterVariable(&r_water_fbo);
4259
4260         Cvar_RegisterVariable(&r_lerpsprites);
4261         Cvar_RegisterVariable(&r_lerpmodels);
4262         Cvar_RegisterVariable(&r_lerplightstyles);
4263         Cvar_RegisterVariable(&r_waterscroll);
4264         Cvar_RegisterVariable(&r_bloom);
4265         Cvar_RegisterVariable(&r_bloom_colorscale);
4266         Cvar_RegisterVariable(&r_bloom_brighten);
4267         Cvar_RegisterVariable(&r_bloom_blur);
4268         Cvar_RegisterVariable(&r_bloom_resolution);
4269         Cvar_RegisterVariable(&r_bloom_colorexponent);
4270         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4271         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4272         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4273         Cvar_RegisterVariable(&r_hdr_glowintensity);
4274         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4275         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4276         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4277         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4278         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4279         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4280         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4281         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4282         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4283         Cvar_RegisterVariable(&developer_texturelogging);
4284         Cvar_RegisterVariable(&gl_lightmaps);
4285         Cvar_RegisterVariable(&r_test);
4286         Cvar_RegisterVariable(&r_batch_multidraw);
4287         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4288         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4289         Cvar_RegisterVariable(&r_glsl_skeletal);
4290         Cvar_RegisterVariable(&r_glsl_saturation);
4291         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4292         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4293         Cvar_RegisterVariable(&r_framedatasize);
4294         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4295                 Cvar_SetValue("r_fullbrights", 0);
4296         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4297 }
4298
4299 void Render_Init(void)
4300 {
4301         gl_backend_init();
4302         R_Textures_Init();
4303         GL_Main_Init();
4304         Font_Init();
4305         GL_Draw_Init();
4306         R_Shadow_Init();
4307         R_Sky_Init();
4308         GL_Surf_Init();
4309         Sbar_Init();
4310         R_Particles_Init();
4311         R_Explosion_Init();
4312         R_LightningBeams_Init();
4313         Mod_RenderInit();
4314 }
4315
4316 /*
4317 ===============
4318 GL_Init
4319 ===============
4320 */
4321 #ifndef USE_GLES2
4322 extern char *ENGINE_EXTENSIONS;
4323 void GL_Init (void)
4324 {
4325         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4326         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4327         gl_version = (const char *)qglGetString(GL_VERSION);
4328         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4329
4330         if (!gl_extensions)
4331                 gl_extensions = "";
4332         if (!gl_platformextensions)
4333                 gl_platformextensions = "";
4334
4335         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4336         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4337         Con_Printf("GL_VERSION: %s\n", gl_version);
4338         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4339         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4340
4341         VID_CheckExtensions();
4342
4343         // LordHavoc: report supported extensions
4344         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4345
4346         // clear to black (loading plaque will be seen over this)
4347         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4348 }
4349 #endif
4350
4351 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4352 {
4353         int i;
4354         mplane_t *p;
4355         if (r_trippy.integer)
4356                 return false;
4357         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4358         {
4359                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4360                 if (i == 4)
4361                         continue;
4362                 p = r_refdef.view.frustum + i;
4363                 switch(p->signbits)
4364                 {
4365                 default:
4366                 case 0:
4367                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4368                                 return true;
4369                         break;
4370                 case 1:
4371                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4372                                 return true;
4373                         break;
4374                 case 2:
4375                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4376                                 return true;
4377                         break;
4378                 case 3:
4379                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 4:
4383                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 5:
4387                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 6:
4391                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 7:
4395                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 }
4399         }
4400         return false;
4401 }
4402
4403 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4404 {
4405         int i;
4406         const mplane_t *p;
4407         if (r_trippy.integer)
4408                 return false;
4409         for (i = 0;i < numplanes;i++)
4410         {
4411                 p = planes + i;
4412                 switch(p->signbits)
4413                 {
4414                 default:
4415                 case 0:
4416                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 1:
4420                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 2:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 3:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 4:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 5:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 6:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 7:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 }
4448         }
4449         return false;
4450 }
4451
4452 //==================================================================================
4453
4454 // LordHavoc: this stores temporary data used within the same frame
4455
4456 typedef struct r_framedata_mem_s
4457 {
4458         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4459         size_t size; // how much usable space
4460         size_t current; // how much space in use
4461         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4462         size_t wantedsize; // how much space was allocated
4463         unsigned char *data; // start of real data (16byte aligned)
4464 }
4465 r_framedata_mem_t;
4466
4467 static r_framedata_mem_t *r_framedata_mem;
4468
4469 void R_FrameData_Reset(void)
4470 {
4471         while (r_framedata_mem)
4472         {
4473                 r_framedata_mem_t *next = r_framedata_mem->purge;
4474                 Mem_Free(r_framedata_mem);
4475                 r_framedata_mem = next;
4476         }
4477 }
4478
4479 static void R_FrameData_Resize(void)
4480 {
4481         size_t wantedsize;
4482         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4483         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4484         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4485         {
4486                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4487                 newmem->wantedsize = wantedsize;
4488                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4489                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4490                 newmem->current = 0;
4491                 newmem->mark = 0;
4492                 newmem->purge = r_framedata_mem;
4493                 r_framedata_mem = newmem;
4494         }
4495 }
4496
4497 void R_FrameData_NewFrame(void)
4498 {
4499         R_FrameData_Resize();
4500         if (!r_framedata_mem)
4501                 return;
4502         // if we ran out of space on the last frame, free the old memory now
4503         while (r_framedata_mem->purge)
4504         {
4505                 // repeatedly remove the second item in the list, leaving only head
4506                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4507                 Mem_Free(r_framedata_mem->purge);
4508                 r_framedata_mem->purge = next;
4509         }
4510         // reset the current mem pointer
4511         r_framedata_mem->current = 0;
4512         r_framedata_mem->mark = 0;
4513 }
4514
4515 void *R_FrameData_Alloc(size_t size)
4516 {
4517         void *data;
4518
4519         // align to 16 byte boundary - the data pointer is already aligned, so we
4520         // only need to ensure the size of every allocation is also aligned
4521         size = (size + 15) & ~15;
4522
4523         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4524         {
4525                 // emergency - we ran out of space, allocate more memory
4526                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4527                 R_FrameData_Resize();
4528         }
4529
4530         data = r_framedata_mem->data + r_framedata_mem->current;
4531         r_framedata_mem->current += size;
4532
4533         // count the usage for stats
4534         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4535         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4536
4537         return (void *)data;
4538 }
4539
4540 void *R_FrameData_Store(size_t size, void *data)
4541 {
4542         void *d = R_FrameData_Alloc(size);
4543         if (d && data)
4544                 memcpy(d, data, size);
4545         return d;
4546 }
4547
4548 void R_FrameData_SetMark(void)
4549 {
4550         if (!r_framedata_mem)
4551                 return;
4552         r_framedata_mem->mark = r_framedata_mem->current;
4553 }
4554
4555 void R_FrameData_ReturnToMark(void)
4556 {
4557         if (!r_framedata_mem)
4558                 return;
4559         r_framedata_mem->current = r_framedata_mem->mark;
4560 }
4561
4562 //==================================================================================
4563
4564 // LordHavoc: animcache originally written by Echon, rewritten since then
4565
4566 /**
4567  * Animation cache prevents re-generating mesh data for an animated model
4568  * multiple times in one frame for lighting, shadowing, reflections, etc.
4569  */
4570
4571 void R_AnimCache_Free(void)
4572 {
4573 }
4574
4575 void R_AnimCache_ClearCache(void)
4576 {
4577         int i;
4578         entity_render_t *ent;
4579
4580         for (i = 0;i < r_refdef.scene.numentities;i++)
4581         {
4582                 ent = r_refdef.scene.entities[i];
4583                 ent->animcache_vertex3f = NULL;
4584                 ent->animcache_normal3f = NULL;
4585                 ent->animcache_svector3f = NULL;
4586                 ent->animcache_tvector3f = NULL;
4587                 ent->animcache_vertexmesh = NULL;
4588                 ent->animcache_vertex3fbuffer = NULL;
4589                 ent->animcache_vertexmeshbuffer = NULL;
4590                 ent->animcache_skeletaltransform3x4 = NULL;
4591         }
4592 }
4593
4594 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4595 {
4596         int i;
4597
4598         // check if we need the meshbuffers
4599         if (!vid.useinterleavedarrays)
4600                 return;
4601
4602         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4603                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4604         // TODO: upload vertex3f buffer?
4605         if (ent->animcache_vertexmesh)
4606         {
4607                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4608                 for (i = 0;i < numvertices;i++)
4609                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4610                 if (ent->animcache_svector3f)
4611                         for (i = 0;i < numvertices;i++)
4612                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4613                 if (ent->animcache_tvector3f)
4614                         for (i = 0;i < numvertices;i++)
4615                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4616                 if (ent->animcache_normal3f)
4617                         for (i = 0;i < numvertices;i++)
4618                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4619                 // TODO: upload vertexmeshbuffer?
4620         }
4621 }
4622
4623 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4624 {
4625         dp_model_t *model = ent->model;
4626         int numvertices;
4627
4628         // cache skeletal animation data first (primarily for gpu-skinning)
4629         if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4630         {
4631                 int i;
4632                 int blends;
4633                 const skeleton_t *skeleton = ent->skeleton;
4634                 const frameblend_t *frameblend = ent->frameblend;
4635                 float *boneposerelative;
4636                 float m[12];
4637                 static float bonepose[256][12];
4638                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4639                 boneposerelative = ent->animcache_skeletaltransform3x4;
4640                 if (skeleton && !skeleton->relativetransforms)
4641                         skeleton = NULL;
4642                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4643                 if (skeleton)
4644                 {
4645                         for (i = 0;i < model->num_bones;i++)
4646                         {
4647                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4648                                 if (model->data_bones[i].parent >= 0)
4649                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4650                                 else
4651                                         memcpy(bonepose[i], m, sizeof(m));
4652
4653                                 // create a relative deformation matrix to describe displacement
4654                                 // from the base mesh, which is used by the actual weighting
4655                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4656                         }
4657                 }
4658                 else
4659                 {
4660                         for (i = 0;i < model->num_bones;i++)
4661                         {
4662                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4663                                 float lerp = frameblend[0].lerp,
4664                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4665                                         rx = pose7s[3] * lerp,
4666                                         ry = pose7s[4] * lerp,
4667                                         rz = pose7s[5] * lerp,
4668                                         rw = pose7s[6] * lerp,
4669                                         dx = tx*rw + ty*rz - tz*ry,
4670                                         dy = -tx*rz + ty*rw + tz*rx,
4671                                         dz = tx*ry - ty*rx + tz*rw,
4672                                         dw = -tx*rx - ty*ry - tz*rz,
4673                                         scale, sx, sy, sz, sw;
4674                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4675                                 {
4676                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4677                                         float lerp = frameblend[blends].lerp,
4678                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4679                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4680                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4681                                         qx *= lerp;
4682                                         qy *= lerp;
4683                                         qz *= lerp;
4684                                         qw *= lerp;
4685                                         rx += qx;
4686                                         ry += qy;
4687                                         rz += qz;
4688                                         rw += qw;
4689                                         dx += tx*qw + ty*qz - tz*qy;
4690                                         dy += -tx*qz + ty*qw + tz*qx;
4691                                         dz += tx*qy - ty*qx + tz*qw;
4692                                         dw += -tx*qx - ty*qy - tz*qz;
4693                                 }
4694                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4695                                 sx = rx * scale;
4696                                 sy = ry * scale;
4697                                 sz = rz * scale;
4698                                 sw = rw * scale;
4699                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4700                                 m[1] = 2*(sx*ry - sw*rz);
4701                                 m[2] = 2*(sx*rz + sw*ry);
4702                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4703                                 m[4] = 2*(sx*ry + sw*rz);
4704                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4705                                 m[6] = 2*(sy*rz - sw*rx);
4706                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4707                                 m[8] = 2*(sx*rz - sw*ry);
4708                                 m[9] = 2*(sy*rz + sw*rx);
4709                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4710                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4711                                 if (i == r_skeletal_debugbone.integer)
4712                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4713                                 m[3] *= r_skeletal_debugtranslatex.value;
4714                                 m[7] *= r_skeletal_debugtranslatey.value;
4715                                 m[11] *= r_skeletal_debugtranslatez.value;
4716                                 if (model->data_bones[i].parent >= 0)
4717                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4718                                 else
4719                                         memcpy(bonepose[i], m, sizeof(m));
4720                                 // create a relative deformation matrix to describe displacement
4721                                 // from the base mesh, which is used by the actual weighting
4722                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4723                         }
4724                 }
4725         }
4726
4727         // see if it's already cached this frame
4728         if (ent->animcache_vertex3f)
4729         {
4730                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4731                 if (wantnormals || wanttangents)
4732                 {
4733                         if (ent->animcache_normal3f)
4734                                 wantnormals = false;
4735                         if (ent->animcache_svector3f)
4736                                 wanttangents = false;
4737                         if (wantnormals || wanttangents)
4738                         {
4739                                 numvertices = model->surfmesh.num_vertices;
4740                                 if (wantnormals)
4741                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4742                                 if (wanttangents)
4743                                 {
4744                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4745                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4746                                 }
4747                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4748                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4749                         }
4750                 }
4751         }
4752         else
4753         {
4754                 // see if this ent is worth caching
4755                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4756                         return false;
4757                 // skip entity if the shader backend has a cheaper way
4758                 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer && !r_showsurfaces.integer) // FIXME add r_showsurfaces support to GLSL skeletal!
4759                 {
4760                         switch (vid.renderpath)
4761                         {
4762                         case RENDERPATH_GL20:
4763                                 return false;
4764                         case RENDERPATH_GL11:
4765                         case RENDERPATH_GL13:
4766                         case RENDERPATH_GLES1:
4767                         case RENDERPATH_GLES2:
4768                         case RENDERPATH_D3D9:
4769                         case RENDERPATH_D3D10:
4770                         case RENDERPATH_D3D11:
4771                         case RENDERPATH_SOFT:
4772                                 break;
4773                         }
4774                 }
4775                 // get some memory for this entity and generate mesh data
4776                 numvertices = model->surfmesh.num_vertices;
4777                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4778                 if (wantnormals)
4779                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4780                 if (wanttangents)
4781                 {
4782                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4783                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4784                 }
4785                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4786                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4787         }
4788         return true;
4789 }
4790
4791 void R_AnimCache_CacheVisibleEntities(void)
4792 {
4793         int i;
4794         qboolean wantnormals = true;
4795         qboolean wanttangents = !r_showsurfaces.integer;
4796
4797         switch(vid.renderpath)
4798         {
4799         case RENDERPATH_GL20:
4800         case RENDERPATH_D3D9:
4801         case RENDERPATH_D3D10:
4802         case RENDERPATH_D3D11:
4803         case RENDERPATH_GLES2:
4804                 break;
4805         case RENDERPATH_GL11:
4806         case RENDERPATH_GL13:
4807         case RENDERPATH_GLES1:
4808                 wanttangents = false;
4809                 break;
4810         case RENDERPATH_SOFT:
4811                 break;
4812         }
4813
4814         if (r_shownormals.integer)
4815                 wanttangents = wantnormals = true;
4816
4817         // TODO: thread this
4818         // NOTE: R_PrepareRTLights() also caches entities
4819
4820         for (i = 0;i < r_refdef.scene.numentities;i++)
4821                 if (r_refdef.viewcache.entityvisible[i])
4822                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4823 }
4824
4825 //==================================================================================
4826
4827 extern cvar_t r_overheadsprites_pushback;
4828
4829 static void R_View_UpdateEntityLighting (void)
4830 {
4831         int i;
4832         entity_render_t *ent;
4833         vec3_t tempdiffusenormal, avg;
4834         vec_t f, fa, fd, fdd;
4835         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4836
4837         for (i = 0;i < r_refdef.scene.numentities;i++)
4838         {
4839                 ent = r_refdef.scene.entities[i];
4840
4841                 // skip unseen models
4842                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4843                         continue;
4844
4845                 // skip bsp models
4846                 if (ent->model && ent->model == cl.worldmodel)
4847                 {
4848                         // TODO: use modellight for r_ambient settings on world?
4849                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4850                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4851                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4852                         continue;
4853                 }
4854                 
4855                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4856                 {
4857                         // aleady updated by CSQC
4858                         // TODO: force modellight on BSP models in this case?
4859                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4860                 }
4861                 else
4862                 {
4863                         // fetch the lighting from the worldmodel data
4864                         VectorClear(ent->modellight_ambient);
4865                         VectorClear(ent->modellight_diffuse);
4866                         VectorClear(tempdiffusenormal);
4867                         if (ent->flags & RENDER_LIGHT)
4868                         {
4869                                 vec3_t org;
4870                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4871
4872                                 // complete lightning for lit sprites
4873                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4874                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4875                                 {
4876                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4877                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4878                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4879                                 }
4880                                 else
4881                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4882
4883                                 if(ent->flags & RENDER_EQUALIZE)
4884                                 {
4885                                         // first fix up ambient lighting...
4886                                         if(r_equalize_entities_minambient.value > 0)
4887                                         {
4888                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4889                                                 if(fd > 0)
4890                                                 {
4891                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4892                                                         if(fa < r_equalize_entities_minambient.value * fd)
4893                                                         {
4894                                                                 // solve:
4895                                                                 //   fa'/fd' = minambient
4896                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4897                                                                 //   ...
4898                                                                 //   fa' = fd' * minambient
4899                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4900                                                                 //   ...
4901                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4902                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4903                                                                 //   ...
4904                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4905                                                                 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
4906                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4907                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4908                                                         }
4909                                                 }
4910                                         }
4911
4912                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4913                                         {
4914                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4915                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4916                                                 f = fa + 0.25 * fd;
4917                                                 if(f > 0)
4918                                                 {
4919                                                         // adjust brightness and saturation to target
4920                                                         avg[0] = avg[1] = avg[2] = fa / f;
4921                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4922                                                         avg[0] = avg[1] = avg[2] = fd / f;
4923                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4924                                                 }
4925                                         }
4926                                 }
4927                         }
4928                         else // highly rare
4929                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4930                 }
4931
4932                 // move the light direction into modelspace coordinates for lighting code
4933                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4934                 if(VectorLength2(ent->modellight_lightdir) == 0)
4935                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4936                 VectorNormalize(ent->modellight_lightdir);
4937         }
4938 }
4939
4940 #define MAX_LINEOFSIGHTTRACES 64
4941
4942 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4943 {
4944         int i;
4945         vec3_t boxmins, boxmaxs;
4946         vec3_t start;
4947         vec3_t end;
4948         dp_model_t *model = r_refdef.scene.worldmodel;
4949
4950         if (!model || !model->brush.TraceLineOfSight)
4951                 return true;
4952
4953         // expand the box a little
4954         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4955         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4956         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4957         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4958         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4959         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4960
4961         // return true if eye is inside enlarged box
4962         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4963                 return true;
4964
4965         // try center
4966         VectorCopy(eye, start);
4967         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4968         if (model->brush.TraceLineOfSight(model, start, end))
4969                 return true;
4970
4971         // try various random positions
4972         for (i = 0;i < numsamples;i++)
4973         {
4974                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4975                 if (model->brush.TraceLineOfSight(model, start, end))
4976                         return true;
4977         }
4978
4979         return false;
4980 }
4981
4982
4983 static void R_View_UpdateEntityVisible (void)
4984 {
4985         int i;
4986         int renderimask;
4987         int samples;
4988         entity_render_t *ent;
4989
4990         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4991                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4992                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4993                 :                                                          RENDER_EXTERIORMODEL;
4994         if (!r_drawviewmodel.integer)
4995                 renderimask |= RENDER_VIEWMODEL;
4996         if (!r_drawexteriormodel.integer)
4997                 renderimask |= RENDER_EXTERIORMODEL;
4998         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4999         {
5000                 // worldmodel can check visibility
5001                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5002                 for (i = 0;i < r_refdef.scene.numentities;i++)
5003                 {
5004                         ent = r_refdef.scene.entities[i];
5005                         if (!(ent->flags & renderimask))
5006                         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)))
5007                         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))
5008                                 r_refdef.viewcache.entityvisible[i] = true;
5009                 }
5010         }
5011         else
5012         {
5013                 // no worldmodel or it can't check visibility
5014                 for (i = 0;i < r_refdef.scene.numentities;i++)
5015                 {
5016                         ent = r_refdef.scene.entities[i];
5017                         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));
5018                 }
5019         }
5020         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5021                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5022         {
5023                 for (i = 0;i < r_refdef.scene.numentities;i++)
5024                 {
5025                         if (!r_refdef.viewcache.entityvisible[i])
5026                                 continue;
5027                         ent = r_refdef.scene.entities[i];
5028                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5029                         {
5030                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5031                                 if (samples < 0)
5032                                         continue; // temp entities do pvs only
5033                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5034                                         ent->last_trace_visibility = realtime;
5035                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5036                                         r_refdef.viewcache.entityvisible[i] = 0;
5037                         }
5038                 }
5039         }
5040 }
5041
5042 /// only used if skyrendermasked, and normally returns false
5043 static int R_DrawBrushModelsSky (void)
5044 {
5045         int i, sky;
5046         entity_render_t *ent;
5047
5048         sky = false;
5049         for (i = 0;i < r_refdef.scene.numentities;i++)
5050         {
5051                 if (!r_refdef.viewcache.entityvisible[i])
5052                         continue;
5053                 ent = r_refdef.scene.entities[i];
5054                 if (!ent->model || !ent->model->DrawSky)
5055                         continue;
5056                 ent->model->DrawSky(ent);
5057                 sky = true;
5058         }
5059         return sky;
5060 }
5061
5062 static void R_DrawNoModel(entity_render_t *ent);
5063 static void R_DrawModels(void)
5064 {
5065         int i;
5066         entity_render_t *ent;
5067
5068         for (i = 0;i < r_refdef.scene.numentities;i++)
5069         {
5070                 if (!r_refdef.viewcache.entityvisible[i])
5071                         continue;
5072                 ent = r_refdef.scene.entities[i];
5073                 r_refdef.stats.entities++;
5074                 /*
5075                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5076                 {
5077                         vec3_t f, l, u, o;
5078                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5079                         Con_Printf("R_DrawModels\n");
5080                         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]);
5081                         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);
5082                         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);
5083                 }
5084                 */
5085                 if (ent->model && ent->model->Draw != NULL)
5086                         ent->model->Draw(ent);
5087                 else
5088                         R_DrawNoModel(ent);
5089         }
5090 }
5091
5092 static void R_DrawModelsDepth(void)
5093 {
5094         int i;
5095         entity_render_t *ent;
5096
5097         for (i = 0;i < r_refdef.scene.numentities;i++)
5098         {
5099                 if (!r_refdef.viewcache.entityvisible[i])
5100                         continue;
5101                 ent = r_refdef.scene.entities[i];
5102                 if (ent->model && ent->model->DrawDepth != NULL)
5103                         ent->model->DrawDepth(ent);
5104         }
5105 }
5106
5107 static void R_DrawModelsDebug(void)
5108 {
5109         int i;
5110         entity_render_t *ent;
5111
5112         for (i = 0;i < r_refdef.scene.numentities;i++)
5113         {
5114                 if (!r_refdef.viewcache.entityvisible[i])
5115                         continue;
5116                 ent = r_refdef.scene.entities[i];
5117                 if (ent->model && ent->model->DrawDebug != NULL)
5118                         ent->model->DrawDebug(ent);
5119         }
5120 }
5121
5122 static void R_DrawModelsAddWaterPlanes(void)
5123 {
5124         int i;
5125         entity_render_t *ent;
5126
5127         for (i = 0;i < r_refdef.scene.numentities;i++)
5128         {
5129                 if (!r_refdef.viewcache.entityvisible[i])
5130                         continue;
5131                 ent = r_refdef.scene.entities[i];
5132                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5133                         ent->model->DrawAddWaterPlanes(ent);
5134         }
5135 }
5136
5137 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}};
5138
5139 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5140 {
5141         if (r_hdr_irisadaptation.integer)
5142         {
5143                 vec3_t p;
5144                 vec3_t ambient;
5145                 vec3_t diffuse;
5146                 vec3_t diffusenormal;
5147                 vec3_t forward;
5148                 vec_t brightness = 0.0f;
5149                 vec_t goal;
5150                 vec_t current;
5151                 vec_t d;
5152                 int c;
5153                 VectorCopy(r_refdef.view.forward, forward);
5154                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5155                 {
5156                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5157                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5158                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5159                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5160                         d = DotProduct(forward, diffusenormal);
5161                         brightness += VectorLength(ambient);
5162                         if (d > 0)
5163                                 brightness += d * VectorLength(diffuse);
5164                 }
5165                 brightness *= 1.0f / c;
5166                 brightness += 0.00001f; // make sure it's never zero
5167                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5168                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5169                 current = r_hdr_irisadaptation_value.value;
5170                 if (current < goal)
5171                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5172                 else if (current > goal)
5173                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5174                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5175                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5176         }
5177         else if (r_hdr_irisadaptation_value.value != 1.0f)
5178                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5179 }
5180
5181 static void R_View_SetFrustum(const int *scissor)
5182 {
5183         int i;
5184         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5185         vec3_t forward, left, up, origin, v;
5186
5187         if(scissor)
5188         {
5189                 // flipped x coordinates (because x points left here)
5190                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5191                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5192
5193                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5194                 switch(vid.renderpath)
5195                 {
5196                         case RENDERPATH_D3D9:
5197                         case RENDERPATH_D3D10:
5198                         case RENDERPATH_D3D11:
5199                                 // non-flipped y coordinates
5200                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5201                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5202                                 break;
5203                         case RENDERPATH_SOFT:
5204                         case RENDERPATH_GL11:
5205                         case RENDERPATH_GL13:
5206                         case RENDERPATH_GL20:
5207                         case RENDERPATH_GLES1:
5208                         case RENDERPATH_GLES2:
5209                                 // non-flipped y coordinates
5210                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5211                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5212                                 break;
5213                 }
5214         }
5215
5216         // we can't trust r_refdef.view.forward and friends in reflected scenes
5217         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5218
5219 #if 0
5220         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5221         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5222         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5223         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5224         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5225         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5226         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5227         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5228         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5229         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5230         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5231         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5232 #endif
5233
5234 #if 0
5235         zNear = r_refdef.nearclip;
5236         nudge = 1.0 - 1.0 / (1<<23);
5237         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5238         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5239         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5240         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5241         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5242         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5243         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5244         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5245 #endif
5246
5247
5248
5249 #if 0
5250         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5251         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5252         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5253         r_refdef.view.frustum[0].dist = m[15] - m[12];
5254
5255         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5256         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5257         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5258         r_refdef.view.frustum[1].dist = m[15] + m[12];
5259
5260         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5261         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5262         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5263         r_refdef.view.frustum[2].dist = m[15] - m[13];
5264
5265         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5266         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5267         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5268         r_refdef.view.frustum[3].dist = m[15] + m[13];
5269
5270         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5271         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5272         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5273         r_refdef.view.frustum[4].dist = m[15] - m[14];
5274
5275         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5276         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5277         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5278         r_refdef.view.frustum[5].dist = m[15] + m[14];
5279 #endif
5280
5281         if (r_refdef.view.useperspective)
5282         {
5283                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5284                 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]);
5285                 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]);
5286                 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]);
5287                 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]);
5288
5289                 // then the normals from the corners relative to origin
5290                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5291                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5292                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5293                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5294
5295                 // in a NORMAL view, forward cross left == up
5296                 // in a REFLECTED view, forward cross left == down
5297                 // so our cross products above need to be adjusted for a left handed coordinate system
5298                 CrossProduct(forward, left, v);
5299                 if(DotProduct(v, up) < 0)
5300                 {
5301                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5302                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5303                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5304                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5305                 }
5306
5307                 // Leaving those out was a mistake, those were in the old code, and they
5308                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5309                 // I couldn't reproduce it after adding those normalizations. --blub
5310                 VectorNormalize(r_refdef.view.frustum[0].normal);
5311                 VectorNormalize(r_refdef.view.frustum[1].normal);
5312                 VectorNormalize(r_refdef.view.frustum[2].normal);
5313                 VectorNormalize(r_refdef.view.frustum[3].normal);
5314
5315                 // make the corners absolute
5316                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5317                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5318                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5319                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5320
5321                 // one more normal
5322                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5323
5324                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5325                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5326                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5327                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5328                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5329         }
5330         else
5331         {
5332                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5333                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5334                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5335                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5336                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5337                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5338                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5339                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5340                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5341                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5342         }
5343         r_refdef.view.numfrustumplanes = 5;
5344
5345         if (r_refdef.view.useclipplane)
5346         {
5347                 r_refdef.view.numfrustumplanes = 6;
5348                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5349         }
5350
5351         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5352                 PlaneClassify(r_refdef.view.frustum + i);
5353
5354         // LordHavoc: note to all quake engine coders, Quake had a special case
5355         // for 90 degrees which assumed a square view (wrong), so I removed it,
5356         // Quake2 has it disabled as well.
5357
5358         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5359         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5360         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5361         //PlaneClassify(&frustum[0]);
5362
5363         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5364         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5365         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5366         //PlaneClassify(&frustum[1]);
5367
5368         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5369         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5370         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5371         //PlaneClassify(&frustum[2]);
5372
5373         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5374         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5375         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5376         //PlaneClassify(&frustum[3]);
5377
5378         // nearclip plane
5379         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5380         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5381         //PlaneClassify(&frustum[4]);
5382 }
5383
5384 static void R_View_UpdateWithScissor(const int *myscissor)
5385 {
5386         R_Main_ResizeViewCache();
5387         R_View_SetFrustum(myscissor);
5388         R_View_WorldVisibility(r_refdef.view.useclipplane);
5389         R_View_UpdateEntityVisible();
5390         R_View_UpdateEntityLighting();
5391 }
5392
5393 static void R_View_Update(void)
5394 {
5395         R_Main_ResizeViewCache();
5396         R_View_SetFrustum(NULL);
5397         R_View_WorldVisibility(r_refdef.view.useclipplane);
5398         R_View_UpdateEntityVisible();
5399         R_View_UpdateEntityLighting();
5400 }
5401
5402 float viewscalefpsadjusted = 1.0f;
5403
5404 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5405 {
5406         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5407         scale = bound(0.03125f, scale, 1.0f);
5408         *outwidth = (int)ceil(width * scale);
5409         *outheight = (int)ceil(height * scale);
5410 }
5411
5412 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5413 {
5414         const float *customclipplane = NULL;
5415         float plane[4];
5416         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5417         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5418         {
5419                 // LordHavoc: couldn't figure out how to make this approach the
5420                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5421                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5422                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5423                         dist = r_refdef.view.clipplane.dist;
5424                 plane[0] = r_refdef.view.clipplane.normal[0];
5425                 plane[1] = r_refdef.view.clipplane.normal[1];
5426                 plane[2] = r_refdef.view.clipplane.normal[2];
5427                 plane[3] = -dist;
5428                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5429         }
5430
5431         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5432         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5433
5434         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5435         if (!r_refdef.view.useperspective)
5436                 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);
5437         else if (vid.stencil && r_useinfinitefarclip.integer)
5438                 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);
5439         else
5440                 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);
5441         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5442         R_SetViewport(&r_refdef.view.viewport);
5443         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5444         {
5445                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5446                 float screenplane[4];
5447                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5448                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5449                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5450                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5451                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5452         }
5453 }
5454
5455 void R_EntityMatrix(const matrix4x4_t *matrix)
5456 {
5457         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5458         {
5459                 gl_modelmatrixchanged = false;
5460                 gl_modelmatrix = *matrix;
5461                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5462                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5463                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5464                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5465                 CHECKGLERROR
5466                 switch(vid.renderpath)
5467                 {
5468                 case RENDERPATH_D3D9:
5469 #ifdef SUPPORTD3D
5470                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5471                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5472 #endif
5473                         break;
5474                 case RENDERPATH_D3D10:
5475                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5476                         break;
5477                 case RENDERPATH_D3D11:
5478                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5479                         break;
5480                 case RENDERPATH_GL11:
5481                 case RENDERPATH_GL13:
5482                 case RENDERPATH_GLES1:
5483                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5484                         break;
5485                 case RENDERPATH_SOFT:
5486                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5487                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5488                         break;
5489                 case RENDERPATH_GL20:
5490                 case RENDERPATH_GLES2:
5491                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5492                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5493                         break;
5494                 }
5495         }
5496 }
5497
5498 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5499 {
5500         r_viewport_t viewport;
5501
5502         CHECKGLERROR
5503
5504         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5505         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);
5506         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5507         R_SetViewport(&viewport);
5508         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5509         GL_Color(1, 1, 1, 1);
5510         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5511         GL_BlendFunc(GL_ONE, GL_ZERO);
5512         GL_ScissorTest(false);
5513         GL_DepthMask(false);
5514         GL_DepthRange(0, 1);
5515         GL_DepthTest(false);
5516         GL_DepthFunc(GL_LEQUAL);
5517         R_EntityMatrix(&identitymatrix);
5518         R_Mesh_ResetTextureState();
5519         GL_PolygonOffset(0, 0);
5520         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5521         switch(vid.renderpath)
5522         {
5523         case RENDERPATH_GL11:
5524         case RENDERPATH_GL13:
5525         case RENDERPATH_GL20:
5526         case RENDERPATH_GLES1:
5527         case RENDERPATH_GLES2:
5528                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5529                 break;
5530         case RENDERPATH_D3D9:
5531         case RENDERPATH_D3D10:
5532         case RENDERPATH_D3D11:
5533         case RENDERPATH_SOFT:
5534                 break;
5535         }
5536         GL_CullFace(GL_NONE);
5537
5538         CHECKGLERROR
5539 }
5540
5541 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5542 {
5543         DrawQ_Finish();
5544
5545         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5546 }
5547
5548 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5549 {
5550         DrawQ_Finish();
5551
5552         R_SetupView(true, fbo, depthtexture, colortexture);
5553         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5554         GL_Color(1, 1, 1, 1);
5555         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5556         GL_BlendFunc(GL_ONE, GL_ZERO);
5557         GL_ScissorTest(true);
5558         GL_DepthMask(true);
5559         GL_DepthRange(0, 1);
5560         GL_DepthTest(true);
5561         GL_DepthFunc(GL_LEQUAL);
5562         R_EntityMatrix(&identitymatrix);
5563         R_Mesh_ResetTextureState();
5564         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5565         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5566         switch(vid.renderpath)
5567         {
5568         case RENDERPATH_GL11:
5569         case RENDERPATH_GL13:
5570         case RENDERPATH_GL20:
5571         case RENDERPATH_GLES1:
5572         case RENDERPATH_GLES2:
5573                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5574                 break;
5575         case RENDERPATH_D3D9:
5576         case RENDERPATH_D3D10:
5577         case RENDERPATH_D3D11:
5578         case RENDERPATH_SOFT:
5579                 break;
5580         }
5581         GL_CullFace(r_refdef.view.cullface_back);
5582 }
5583
5584 /*
5585 ================
5586 R_RenderView_UpdateViewVectors
5587 ================
5588 */
5589 void R_RenderView_UpdateViewVectors(void)
5590 {
5591         // break apart the view matrix into vectors for various purposes
5592         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5593         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5594         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5595         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5596         // make an inverted copy of the view matrix for tracking sprites
5597         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5598 }
5599
5600 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5601 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5602
5603 static void R_Water_StartFrame(void)
5604 {
5605         int i;
5606         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5607         r_waterstate_waterplane_t *p;
5608         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5609
5610         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5611                 return;
5612
5613         switch(vid.renderpath)
5614         {
5615         case RENDERPATH_GL20:
5616         case RENDERPATH_D3D9:
5617         case RENDERPATH_D3D10:
5618         case RENDERPATH_D3D11:
5619         case RENDERPATH_SOFT:
5620         case RENDERPATH_GLES2:
5621                 break;
5622         case RENDERPATH_GL11:
5623         case RENDERPATH_GL13:
5624         case RENDERPATH_GLES1:
5625                 return;
5626         }
5627
5628         // set waterwidth and waterheight to the water resolution that will be
5629         // used (often less than the screen resolution for faster rendering)
5630         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5631
5632         // calculate desired texture sizes
5633         // can't use water if the card does not support the texture size
5634         if (!r_water.integer || r_showsurfaces.integer)
5635                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5636         else if (vid.support.arb_texture_non_power_of_two)
5637         {
5638                 texturewidth = waterwidth;
5639                 textureheight = waterheight;
5640                 camerawidth = waterwidth;
5641                 cameraheight = waterheight;
5642         }
5643         else
5644         {
5645                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5646                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5647                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5648                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5649         }
5650
5651         // allocate textures as needed
5652         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))
5653         {
5654                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5655                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5656                 {
5657                         if (p->texture_refraction)
5658                                 R_FreeTexture(p->texture_refraction);
5659                         p->texture_refraction = NULL;
5660                         if (p->fbo_refraction)
5661                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5662                         p->fbo_refraction = 0;
5663                         if (p->texture_reflection)
5664                                 R_FreeTexture(p->texture_reflection);
5665                         p->texture_reflection = NULL;
5666                         if (p->fbo_reflection)
5667                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5668                         p->fbo_reflection = 0;
5669                         if (p->texture_camera)
5670                                 R_FreeTexture(p->texture_camera);
5671                         p->texture_camera = NULL;
5672                         if (p->fbo_camera)
5673                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5674                         p->fbo_camera = 0;
5675                 }
5676                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5677                 r_fb.water.texturewidth = texturewidth;
5678                 r_fb.water.textureheight = textureheight;
5679                 r_fb.water.camerawidth = camerawidth;
5680                 r_fb.water.cameraheight = cameraheight;
5681         }
5682
5683         if (r_fb.water.texturewidth)
5684         {
5685                 int scaledwidth, scaledheight;
5686
5687                 r_fb.water.enabled = true;
5688
5689                 // water resolution is usually reduced
5690                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5691                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5692                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5693
5694                 // set up variables that will be used in shader setup
5695                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5696                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5697                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5698                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5699         }
5700
5701         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5702         r_fb.water.numwaterplanes = 0;
5703 }
5704
5705 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5706 {
5707         int planeindex, bestplaneindex, vertexindex;
5708         vec3_t mins, maxs, normal, center, v, n;
5709         vec_t planescore, bestplanescore;
5710         mplane_t plane;
5711         r_waterstate_waterplane_t *p;
5712         texture_t *t = R_GetCurrentTexture(surface->texture);
5713
5714         rsurface.texture = t;
5715         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5716         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5717         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5718                 return;
5719         // average the vertex normals, find the surface bounds (after deformvertexes)
5720         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5721         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5722         VectorCopy(n, normal);
5723         VectorCopy(v, mins);
5724         VectorCopy(v, maxs);
5725         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5726         {
5727                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5728                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5729                 VectorAdd(normal, n, normal);
5730                 mins[0] = min(mins[0], v[0]);
5731                 mins[1] = min(mins[1], v[1]);
5732                 mins[2] = min(mins[2], v[2]);
5733                 maxs[0] = max(maxs[0], v[0]);
5734                 maxs[1] = max(maxs[1], v[1]);
5735                 maxs[2] = max(maxs[2], v[2]);
5736         }
5737         VectorNormalize(normal);
5738         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5739
5740         VectorCopy(normal, plane.normal);
5741         VectorNormalize(plane.normal);
5742         plane.dist = DotProduct(center, plane.normal);
5743         PlaneClassify(&plane);
5744         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5745         {
5746                 // skip backfaces (except if nocullface is set)
5747 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5748 //                      return;
5749                 VectorNegate(plane.normal, plane.normal);
5750                 plane.dist *= -1;
5751                 PlaneClassify(&plane);
5752         }
5753
5754
5755         // find a matching plane if there is one
5756         bestplaneindex = -1;
5757         bestplanescore = 1048576.0f;
5758         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5759         {
5760                 if(p->camera_entity == t->camera_entity)
5761                 {
5762                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5763                         if (bestplaneindex < 0 || bestplanescore > planescore)
5764                         {
5765                                 bestplaneindex = planeindex;
5766                                 bestplanescore = planescore;
5767                         }
5768                 }
5769         }
5770         planeindex = bestplaneindex;
5771         p = r_fb.water.waterplanes + planeindex;
5772
5773         // if this surface does not fit any known plane rendered this frame, add one
5774         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5775         {
5776                 // store the new plane
5777                 planeindex = r_fb.water.numwaterplanes++;
5778                 p = r_fb.water.waterplanes + planeindex;
5779                 p->plane = plane;
5780                 // clear materialflags and pvs
5781                 p->materialflags = 0;
5782                 p->pvsvalid = false;
5783                 p->camera_entity = t->camera_entity;
5784                 VectorCopy(mins, p->mins);
5785                 VectorCopy(maxs, p->maxs);
5786         }
5787         else
5788         {
5789                 // merge mins/maxs when we're adding this surface to the plane
5790                 p->mins[0] = min(p->mins[0], mins[0]);
5791                 p->mins[1] = min(p->mins[1], mins[1]);
5792                 p->mins[2] = min(p->mins[2], mins[2]);
5793                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5794                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5795                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5796         }
5797         // merge this surface's materialflags into the waterplane
5798         p->materialflags |= t->currentmaterialflags;
5799         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5800         {
5801                 // merge this surface's PVS into the waterplane
5802                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5803                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5804                 {
5805                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5806                         p->pvsvalid = true;
5807                 }
5808         }
5809 }
5810
5811 extern cvar_t r_drawparticles;
5812 extern cvar_t r_drawdecals;
5813
5814 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5815 {
5816         int myscissor[4];
5817         r_refdef_view_t originalview;
5818         r_refdef_view_t myview;
5819         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;
5820         r_waterstate_waterplane_t *p;
5821         vec3_t visorigin;
5822         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5823         char vabuf[1024];
5824
5825         originalview = r_refdef.view;
5826
5827         // lowquality hack, temporarily shut down some cvars and restore afterwards
5828         qualityreduction = r_water_lowquality.integer;
5829         if (qualityreduction > 0)
5830         {
5831                 if (qualityreduction >= 1)
5832                 {
5833                         old_r_shadows = r_shadows.integer;
5834                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5835                         old_r_dlight = r_shadow_realtime_dlight.integer;
5836                         Cvar_SetValueQuick(&r_shadows, 0);
5837                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5838                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5839                 }
5840                 if (qualityreduction >= 2)
5841                 {
5842                         old_r_dynamic = r_dynamic.integer;
5843                         old_r_particles = r_drawparticles.integer;
5844                         old_r_decals = r_drawdecals.integer;
5845                         Cvar_SetValueQuick(&r_dynamic, 0);
5846                         Cvar_SetValueQuick(&r_drawparticles, 0);
5847                         Cvar_SetValueQuick(&r_drawdecals, 0);
5848                 }
5849         }
5850
5851         // make sure enough textures are allocated
5852         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5853         {
5854                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5855                 {
5856                         if (!p->texture_refraction)
5857                                 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);
5858                         if (!p->texture_refraction)
5859                                 goto error;
5860                         if (usewaterfbo)
5861                         {
5862                                 if (r_fb.water.depthtexture == NULL)
5863                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5864                                 if (p->fbo_refraction == 0)
5865                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5866                         }
5867                 }
5868                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5869                 {
5870                         if (!p->texture_camera)
5871                                 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);
5872                         if (!p->texture_camera)
5873                                 goto error;
5874                         if (usewaterfbo)
5875                         {
5876                                 if (r_fb.water.depthtexture == NULL)
5877                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5878                                 if (p->fbo_camera == 0)
5879                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5880                         }
5881                 }
5882
5883                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5884                 {
5885                         if (!p->texture_reflection)
5886                                 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);
5887                         if (!p->texture_reflection)
5888                                 goto error;
5889                         if (usewaterfbo)
5890                         {
5891                                 if (r_fb.water.depthtexture == NULL)
5892                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5893                                 if (p->fbo_reflection == 0)
5894                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5895                         }
5896                 }
5897         }
5898
5899         // render views
5900         r_refdef.view = originalview;
5901         r_refdef.view.showdebug = false;
5902         r_refdef.view.width = r_fb.water.waterwidth;
5903         r_refdef.view.height = r_fb.water.waterheight;
5904         r_refdef.view.useclipplane = true;
5905         myview = r_refdef.view;
5906         r_fb.water.renderingscene = true;
5907         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5908         {
5909                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5910                 {
5911                         r_refdef.view = myview;
5912                         if(r_water_scissormode.integer)
5913                         {
5914                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5915                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5916                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5917                         }
5918
5919                         // render reflected scene and copy into texture
5920                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5921                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5922                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5923                         r_refdef.view.clipplane = p->plane;
5924                         // reverse the cullface settings for this render
5925                         r_refdef.view.cullface_front = GL_FRONT;
5926                         r_refdef.view.cullface_back = GL_BACK;
5927                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5928                         {
5929                                 r_refdef.view.usecustompvs = true;
5930                                 if (p->pvsvalid)
5931                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5932                                 else
5933                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5934                         }
5935
5936                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5937                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5938                         R_ClearScreen(r_refdef.fogenabled);
5939                         if(r_water_scissormode.integer & 2)
5940                                 R_View_UpdateWithScissor(myscissor);
5941                         else
5942                                 R_View_Update();
5943                         R_AnimCache_CacheVisibleEntities();
5944                         if(r_water_scissormode.integer & 1)
5945                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5946                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5947
5948                         if (!p->fbo_reflection)
5949                                 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);
5950                         r_fb.water.hideplayer = false;
5951                 }
5952
5953                 // render the normal view scene and copy into texture
5954                 // (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)
5955                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5956                 {
5957                         r_refdef.view = myview;
5958                         if(r_water_scissormode.integer)
5959                         {
5960                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5961                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5962                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5963                         }
5964
5965                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5966
5967                         r_refdef.view.clipplane = p->plane;
5968                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5969                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5970
5971                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5972                         {
5973                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5974                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5975                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5976                                 R_RenderView_UpdateViewVectors();
5977                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5978                                 {
5979                                         r_refdef.view.usecustompvs = true;
5980                                         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);
5981                                 }
5982                         }
5983
5984                         PlaneClassify(&r_refdef.view.clipplane);
5985
5986                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5987                         R_ClearScreen(r_refdef.fogenabled);
5988                         if(r_water_scissormode.integer & 2)
5989                                 R_View_UpdateWithScissor(myscissor);
5990                         else
5991                                 R_View_Update();
5992                         R_AnimCache_CacheVisibleEntities();
5993                         if(r_water_scissormode.integer & 1)
5994                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5995                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5996
5997                         if (!p->fbo_refraction)
5998                                 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);
5999                         r_fb.water.hideplayer = false;
6000                 }
6001                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6002                 {
6003                         r_refdef.view = myview;
6004
6005                         r_refdef.view.clipplane = p->plane;
6006                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6007                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6008
6009                         r_refdef.view.width = r_fb.water.camerawidth;
6010                         r_refdef.view.height = r_fb.water.cameraheight;
6011                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6012                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6013                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6014                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6015
6016                         if(p->camera_entity)
6017                         {
6018                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6019                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6020                         }
6021
6022                         // note: all of the view is used for displaying... so
6023                         // there is no use in scissoring
6024
6025                         // reverse the cullface settings for this render
6026                         r_refdef.view.cullface_front = GL_FRONT;
6027                         r_refdef.view.cullface_back = GL_BACK;
6028                         // also reverse the view matrix
6029                         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
6030                         R_RenderView_UpdateViewVectors();
6031                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6032                         {
6033                                 r_refdef.view.usecustompvs = true;
6034                                 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);
6035                         }
6036                         
6037                         // camera needs no clipplane
6038                         r_refdef.view.useclipplane = false;
6039
6040                         PlaneClassify(&r_refdef.view.clipplane);
6041
6042                         r_fb.water.hideplayer = false;
6043
6044                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6045                         R_ClearScreen(r_refdef.fogenabled);
6046                         R_View_Update();
6047                         R_AnimCache_CacheVisibleEntities();
6048                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6049
6050                         if (!p->fbo_camera)
6051                                 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);
6052                         r_fb.water.hideplayer = false;
6053                 }
6054
6055         }
6056         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6057         r_fb.water.renderingscene = false;
6058         r_refdef.view = originalview;
6059         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6060         if (!r_fb.water.depthtexture)
6061                 R_ClearScreen(r_refdef.fogenabled);
6062         R_View_Update();
6063         R_AnimCache_CacheVisibleEntities();
6064         goto finish;
6065 error:
6066         r_refdef.view = originalview;
6067         r_fb.water.renderingscene = false;
6068         Cvar_SetValueQuick(&r_water, 0);
6069         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6070 finish:
6071         // lowquality hack, restore cvars
6072         if (qualityreduction > 0)
6073         {
6074                 if (qualityreduction >= 1)
6075                 {
6076                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6077                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6078                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6079                 }
6080                 if (qualityreduction >= 2)
6081                 {
6082                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6083                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6084                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6085                 }
6086         }
6087 }
6088
6089 static void R_Bloom_StartFrame(void)
6090 {
6091         int i;
6092         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6093         int viewwidth, viewheight;
6094         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6095         textype_t textype = TEXTYPE_COLORBUFFER;
6096
6097         switch (vid.renderpath)
6098         {
6099         case RENDERPATH_GL20:
6100                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6101                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6102                 {
6103                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6104                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6105                 }
6106                 break;
6107         case RENDERPATH_GL11:
6108         case RENDERPATH_GL13:
6109         case RENDERPATH_GLES1:
6110         case RENDERPATH_GLES2:
6111         case RENDERPATH_D3D9:
6112         case RENDERPATH_D3D10:
6113         case RENDERPATH_D3D11:
6114                 r_fb.usedepthtextures = false;
6115                 break;
6116         case RENDERPATH_SOFT:
6117                 r_fb.usedepthtextures = true;
6118                 break;
6119         }
6120
6121         if (r_viewscale_fpsscaling.integer)
6122         {
6123                 double actualframetime;
6124                 double targetframetime;
6125                 double adjust;
6126                 actualframetime = r_refdef.lastdrawscreentime;
6127                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6128                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6129                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6130                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6131                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6132                 viewscalefpsadjusted += adjust;
6133                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6134         }
6135         else
6136                 viewscalefpsadjusted = 1.0f;
6137
6138         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6139
6140         switch(vid.renderpath)
6141         {
6142         case RENDERPATH_GL20:
6143         case RENDERPATH_D3D9:
6144         case RENDERPATH_D3D10:
6145         case RENDERPATH_D3D11:
6146         case RENDERPATH_SOFT:
6147         case RENDERPATH_GLES2:
6148                 break;
6149         case RENDERPATH_GL11:
6150         case RENDERPATH_GL13:
6151         case RENDERPATH_GLES1:
6152                 return;
6153         }
6154
6155         // set bloomwidth and bloomheight to the bloom resolution that will be
6156         // used (often less than the screen resolution for faster rendering)
6157         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6158         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6159         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6160         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6161         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6162
6163         // calculate desired texture sizes
6164         if (vid.support.arb_texture_non_power_of_two)
6165         {
6166                 screentexturewidth = vid.width;
6167                 screentextureheight = vid.height;
6168                 bloomtexturewidth = r_fb.bloomwidth;
6169                 bloomtextureheight = r_fb.bloomheight;
6170         }
6171         else
6172         {
6173                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6174                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6175                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6176                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6177         }
6178
6179         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))
6180         {
6181                 Cvar_SetValueQuick(&r_bloom, 0);
6182                 Cvar_SetValueQuick(&r_motionblur, 0);
6183                 Cvar_SetValueQuick(&r_damageblur, 0);
6184         }
6185
6186         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6187          && !r_bloom.integer
6188          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6189          && !useviewfbo
6190          && r_viewscale.value == 1.0f
6191          && !r_viewscale_fpsscaling.integer)
6192                 screentexturewidth = screentextureheight = 0;
6193         if (!r_bloom.integer)
6194                 bloomtexturewidth = bloomtextureheight = 0;
6195
6196         // allocate textures as needed
6197         if (r_fb.screentexturewidth != screentexturewidth
6198          || r_fb.screentextureheight != screentextureheight
6199          || r_fb.bloomtexturewidth != bloomtexturewidth
6200          || r_fb.bloomtextureheight != bloomtextureheight
6201          || r_fb.textype != textype
6202          || useviewfbo != (r_fb.fbo != 0))
6203         {
6204                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6205                 {
6206                         if (r_fb.bloomtexture[i])
6207                                 R_FreeTexture(r_fb.bloomtexture[i]);
6208                         r_fb.bloomtexture[i] = NULL;
6209
6210                         if (r_fb.bloomfbo[i])
6211                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6212                         r_fb.bloomfbo[i] = 0;
6213                 }
6214
6215                 if (r_fb.fbo)
6216                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6217                 r_fb.fbo = 0;
6218
6219                 if (r_fb.colortexture)
6220                         R_FreeTexture(r_fb.colortexture);
6221                 r_fb.colortexture = NULL;
6222
6223                 if (r_fb.depthtexture)
6224                         R_FreeTexture(r_fb.depthtexture);
6225                 r_fb.depthtexture = NULL;
6226
6227                 if (r_fb.ghosttexture)
6228                         R_FreeTexture(r_fb.ghosttexture);
6229                 r_fb.ghosttexture = NULL;
6230
6231                 r_fb.screentexturewidth = screentexturewidth;
6232                 r_fb.screentextureheight = screentextureheight;
6233                 r_fb.bloomtexturewidth = bloomtexturewidth;
6234                 r_fb.bloomtextureheight = bloomtextureheight;
6235                 r_fb.textype = textype;
6236
6237                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6238                 {
6239                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6240                                 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);
6241                         r_fb.ghosttexture_valid = false;
6242                         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);
6243                         if (useviewfbo)
6244                         {
6245                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6246                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6247                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6248                         }
6249                 }
6250
6251                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6252                 {
6253                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6254                         {
6255                                 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);
6256                                 if (useviewfbo)
6257                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6258                         }
6259                 }
6260         }
6261
6262         // bloom texture is a different resolution
6263         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6264         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6265         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6266         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6267         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6268
6269         // set up a texcoord array for the full resolution screen image
6270         // (we have to keep this around to copy back during final render)
6271         r_fb.screentexcoord2f[0] = 0;
6272         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6273         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6274         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6275         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6276         r_fb.screentexcoord2f[5] = 0;
6277         r_fb.screentexcoord2f[6] = 0;
6278         r_fb.screentexcoord2f[7] = 0;
6279
6280         if(r_fb.fbo) 
6281         {
6282                 for (i = 1;i < 8;i += 2)
6283                 {
6284                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6285                 }
6286         }
6287
6288         // set up a texcoord array for the reduced resolution bloom image
6289         // (which will be additive blended over the screen image)
6290         r_fb.bloomtexcoord2f[0] = 0;
6291         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6292         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6293         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6294         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6295         r_fb.bloomtexcoord2f[5] = 0;
6296         r_fb.bloomtexcoord2f[6] = 0;
6297         r_fb.bloomtexcoord2f[7] = 0;
6298
6299         switch(vid.renderpath)
6300         {
6301         case RENDERPATH_GL11:
6302         case RENDERPATH_GL13:
6303         case RENDERPATH_GL20:
6304         case RENDERPATH_SOFT:
6305         case RENDERPATH_GLES1:
6306         case RENDERPATH_GLES2:
6307                 break;
6308         case RENDERPATH_D3D9:
6309         case RENDERPATH_D3D10:
6310         case RENDERPATH_D3D11:
6311                 for (i = 0;i < 4;i++)
6312                 {
6313                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6314                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6315                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6316                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6317                 }
6318                 break;
6319         }
6320
6321         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6322
6323         if (r_fb.fbo)
6324                 r_refdef.view.clear = true;
6325 }
6326
6327 static void R_Bloom_MakeTexture(void)
6328 {
6329         int x, range, dir;
6330         float xoffset, yoffset, r, brighten;
6331         rtexture_t *intex;
6332         float colorscale = r_bloom_colorscale.value;
6333
6334         r_refdef.stats.bloom++;
6335     
6336 #if 0
6337     // this copy is unnecessary since it happens in R_BlendView already
6338         if (!r_fb.fbo)
6339         {
6340                 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);
6341                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6342         }
6343 #endif
6344
6345         // scale down screen texture to the bloom texture size
6346         CHECKGLERROR
6347         r_fb.bloomindex = 0;
6348         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6349         R_SetViewport(&r_fb.bloomviewport);
6350         GL_DepthTest(false);
6351         GL_BlendFunc(GL_ONE, GL_ZERO);
6352         GL_Color(colorscale, colorscale, colorscale, 1);
6353         // 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...
6354         switch(vid.renderpath)
6355         {
6356         case RENDERPATH_GL11:
6357         case RENDERPATH_GL13:
6358         case RENDERPATH_GL20:
6359         case RENDERPATH_GLES1:
6360         case RENDERPATH_GLES2:
6361         case RENDERPATH_SOFT:
6362                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6363                 break;
6364         case RENDERPATH_D3D9:
6365         case RENDERPATH_D3D10:
6366         case RENDERPATH_D3D11:
6367                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6368                 break;
6369         }
6370         // TODO: do boxfilter scale-down in shader?
6371         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6372         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6373         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6374
6375         // we now have a properly scaled bloom image
6376         if (!r_fb.bloomfbo[r_fb.bloomindex])
6377         {
6378                 // copy it into the bloom texture
6379                 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);
6380                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6381         }
6382
6383         // multiply bloom image by itself as many times as desired
6384         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6385         {
6386                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6387                 r_fb.bloomindex ^= 1;
6388                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6389                 x *= 2;
6390                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6391                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6392                 {
6393                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6394                         GL_Color(r,r,r,1); // apply fix factor
6395                 }
6396                 else
6397                 {
6398                         if(x <= 2)
6399                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6400                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6401                         GL_Color(1,1,1,1); // no fix factor supported here
6402                 }
6403                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6404                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6405                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6406                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6407
6408                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6409                 {
6410                         // copy the darkened image to a texture
6411                         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);
6412                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6413                 }
6414         }
6415
6416         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6417         brighten = r_bloom_brighten.value;
6418         brighten = sqrt(brighten);
6419         if(range >= 1)
6420                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6421
6422         for (dir = 0;dir < 2;dir++)
6423         {
6424                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6425                 r_fb.bloomindex ^= 1;
6426                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6427                 // blend on at multiple vertical offsets to achieve a vertical blur
6428                 // TODO: do offset blends using GLSL
6429                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6430                 GL_BlendFunc(GL_ONE, GL_ZERO);
6431                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6432                 for (x = -range;x <= range;x++)
6433                 {
6434                         if (!dir){xoffset = 0;yoffset = x;}
6435                         else {xoffset = x;yoffset = 0;}
6436                         xoffset /= (float)r_fb.bloomtexturewidth;
6437                         yoffset /= (float)r_fb.bloomtextureheight;
6438                         // compute a texcoord array with the specified x and y offset
6439                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6440                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6441                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6442                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6443                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6444                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6445                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6446                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6447                         // this r value looks like a 'dot' particle, fading sharply to
6448                         // black at the edges
6449                         // (probably not realistic but looks good enough)
6450                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6451                         //r = brighten/(range*2+1);
6452                         r = brighten / (range * 2 + 1);
6453                         if(range >= 1)
6454                                 r *= (1 - x*x/(float)(range*range));
6455                         GL_Color(r, r, r, 1);
6456                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6457                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6458                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6459                         GL_BlendFunc(GL_ONE, GL_ONE);
6460                 }
6461
6462                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6463                 {
6464                         // copy the vertically or horizontally blurred bloom view to a texture
6465                         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);
6466                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6467                 }
6468         }
6469 }
6470
6471 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6472 {
6473         unsigned int permutation;
6474         float uservecs[4][4];
6475
6476         R_EntityMatrix(&identitymatrix);
6477
6478         switch (vid.renderpath)
6479         {
6480         case RENDERPATH_GL20:
6481         case RENDERPATH_D3D9:
6482         case RENDERPATH_D3D10:
6483         case RENDERPATH_D3D11:
6484         case RENDERPATH_SOFT:
6485         case RENDERPATH_GLES2:
6486                 permutation =
6487                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6488                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6489                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6490                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6491                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6492
6493                 if (r_fb.colortexture)
6494                 {
6495                         if (!r_fb.fbo)
6496                         {
6497                                 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);
6498                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6499                         }
6500
6501                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6502                         {
6503                                 // declare variables
6504                                 float blur_factor, blur_mouseaccel, blur_velocity;
6505                                 static float blur_average; 
6506                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6507
6508                                 // set a goal for the factoring
6509                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6510                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6511                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6512                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6513                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6514                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6515
6516                                 // from the goal, pick an averaged value between goal and last value
6517                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6518                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6519
6520                                 // enforce minimum amount of blur 
6521                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6522
6523                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6524
6525                                 // calculate values into a standard alpha
6526                                 cl.motionbluralpha = 1 - exp(-
6527                                                 (
6528                                                  (r_motionblur.value * blur_factor / 80)
6529                                                  +
6530                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6531                                                 )
6532                                                 /
6533                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6534                                           );
6535
6536                                 // randomization for the blur value to combat persistent ghosting
6537                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6538                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6539
6540                                 // apply the blur
6541                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6542                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6543                                 {
6544                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6545                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6546                                         switch(vid.renderpath)
6547                                         {
6548                                         case RENDERPATH_GL11:
6549                                         case RENDERPATH_GL13:
6550                                         case RENDERPATH_GL20:
6551                                         case RENDERPATH_GLES1:
6552                                         case RENDERPATH_GLES2:
6553                                         case RENDERPATH_SOFT:
6554                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6555                                                 break;
6556                                         case RENDERPATH_D3D9:
6557                                         case RENDERPATH_D3D10:
6558                                         case RENDERPATH_D3D11:
6559                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6560                                                 break;
6561                                         }
6562                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6563                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6564                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6565                                 }
6566
6567                                 // updates old view angles for next pass
6568                                 VectorCopy(cl.viewangles, blur_oldangles);
6569
6570                                 // copy view into the ghost texture
6571                                 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);
6572                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6573                                 r_fb.ghosttexture_valid = true;
6574                         }
6575                 }
6576                 else
6577                 {
6578                         // no r_fb.colortexture means we're rendering to the real fb
6579                         // we may still have to do view tint...
6580                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6581                         {
6582                                 // apply a color tint to the whole view
6583                                 R_ResetViewRendering2D(0, NULL, NULL);
6584                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6585                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6586                                 R_SetupShader_Generic_NoTexture(false, true);
6587                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6588                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6589                         }
6590                         break; // no screen processing, no bloom, skip it
6591                 }
6592
6593                 if (r_fb.bloomtexture[0])
6594                 {
6595                         // make the bloom texture
6596                         R_Bloom_MakeTexture();
6597                 }
6598
6599 #if _MSC_VER >= 1400
6600 #define sscanf sscanf_s
6601 #endif
6602                 memset(uservecs, 0, sizeof(uservecs));
6603                 if (r_glsl_postprocess_uservec1_enable.integer)
6604                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6605                 if (r_glsl_postprocess_uservec2_enable.integer)
6606                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6607                 if (r_glsl_postprocess_uservec3_enable.integer)
6608                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6609                 if (r_glsl_postprocess_uservec4_enable.integer)
6610                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6611
6612                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6613                 GL_Color(1, 1, 1, 1);
6614                 GL_BlendFunc(GL_ONE, GL_ZERO);
6615
6616                 switch(vid.renderpath)
6617                 {
6618                 case RENDERPATH_GL20:
6619                 case RENDERPATH_GLES2:
6620                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6621                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6622                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6623                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6624                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6625                         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]);
6626                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6627                         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]);
6628                         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]);
6629                         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]);
6630                         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]);
6631                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6632                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6633                         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);
6634                         break;
6635                 case RENDERPATH_D3D9:
6636 #ifdef SUPPORTD3D
6637                         // 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...
6638                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6639                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6640                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6641                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6642                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6643                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6644                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6645                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6646                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6647                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6648                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6649                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6650                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6651                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6652 #endif
6653                         break;
6654                 case RENDERPATH_D3D10:
6655                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6656                         break;
6657                 case RENDERPATH_D3D11:
6658                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6659                         break;
6660                 case RENDERPATH_SOFT:
6661                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6662                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6663                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6664                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6665                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6666                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6667                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6668                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6669                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6670                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6671                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6672                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6673                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6674                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6675                         break;
6676                 default:
6677                         break;
6678                 }
6679                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6680                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6681                 break;
6682         case RENDERPATH_GL11:
6683         case RENDERPATH_GL13:
6684         case RENDERPATH_GLES1:
6685                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6686                 {
6687                         // apply a color tint to the whole view
6688                         R_ResetViewRendering2D(0, NULL, NULL);
6689                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6690                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6691                         R_SetupShader_Generic_NoTexture(false, true);
6692                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6693                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6694                 }
6695                 break;
6696         }
6697 }
6698
6699 matrix4x4_t r_waterscrollmatrix;
6700
6701 void R_UpdateFog(void)
6702 {
6703         // Nehahra fog
6704         if (gamemode == GAME_NEHAHRA)
6705         {
6706                 if (gl_fogenable.integer)
6707                 {
6708                         r_refdef.oldgl_fogenable = true;
6709                         r_refdef.fog_density = gl_fogdensity.value;
6710                         r_refdef.fog_red = gl_fogred.value;
6711                         r_refdef.fog_green = gl_foggreen.value;
6712                         r_refdef.fog_blue = gl_fogblue.value;
6713                         r_refdef.fog_alpha = 1;
6714                         r_refdef.fog_start = 0;
6715                         r_refdef.fog_end = gl_skyclip.value;
6716                         r_refdef.fog_height = 1<<30;
6717                         r_refdef.fog_fadedepth = 128;
6718                 }
6719                 else if (r_refdef.oldgl_fogenable)
6720                 {
6721                         r_refdef.oldgl_fogenable = false;
6722                         r_refdef.fog_density = 0;
6723                         r_refdef.fog_red = 0;
6724                         r_refdef.fog_green = 0;
6725                         r_refdef.fog_blue = 0;
6726                         r_refdef.fog_alpha = 0;
6727                         r_refdef.fog_start = 0;
6728                         r_refdef.fog_end = 0;
6729                         r_refdef.fog_height = 1<<30;
6730                         r_refdef.fog_fadedepth = 128;
6731                 }
6732         }
6733
6734         // fog parms
6735         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6736         r_refdef.fog_start = max(0, r_refdef.fog_start);
6737         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6738
6739         if (r_refdef.fog_density && r_drawfog.integer)
6740         {
6741                 r_refdef.fogenabled = true;
6742                 // this is the point where the fog reaches 0.9986 alpha, which we
6743                 // consider a good enough cutoff point for the texture
6744                 // (0.9986 * 256 == 255.6)
6745                 if (r_fog_exp2.integer)
6746                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6747                 else
6748                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6749                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6750                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6751                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6752                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6753                         R_BuildFogHeightTexture();
6754                 // fog color was already set
6755                 // update the fog texture
6756                 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)
6757                         R_BuildFogTexture();
6758                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6759                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6760         }
6761         else
6762                 r_refdef.fogenabled = false;
6763
6764         // fog color
6765         if (r_refdef.fog_density)
6766         {
6767                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6768                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6769                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6770
6771                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6772                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6773                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6774                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6775
6776                 {
6777                         vec3_t fogvec;
6778                         VectorCopy(r_refdef.fogcolor, fogvec);
6779                         //   color.rgb *= ContrastBoost * SceneBrightness;
6780                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6781                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6782                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6783                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6784                 }
6785         }
6786 }
6787
6788 void R_UpdateVariables(void)
6789 {
6790         R_Textures_Frame();
6791
6792         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6793
6794         r_refdef.farclip = r_farclip_base.value;
6795         if (r_refdef.scene.worldmodel)
6796                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6797         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6798
6799         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6800                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6801         r_refdef.polygonfactor = 0;
6802         r_refdef.polygonoffset = 0;
6803         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6804         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6805
6806         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6807         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6808         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6809         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6810         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6811         if (FAKELIGHT_ENABLED)
6812         {
6813                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6814         }
6815         else if (r_refdef.scene.worldmodel)
6816         {
6817                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6818         }
6819         if (r_showsurfaces.integer)
6820         {
6821                 r_refdef.scene.rtworld = false;
6822                 r_refdef.scene.rtworldshadows = false;
6823                 r_refdef.scene.rtdlight = false;
6824                 r_refdef.scene.rtdlightshadows = false;
6825                 r_refdef.lightmapintensity = 0;
6826         }
6827
6828         switch(vid.renderpath)
6829         {
6830         case RENDERPATH_GL20:
6831         case RENDERPATH_D3D9:
6832         case RENDERPATH_D3D10:
6833         case RENDERPATH_D3D11:
6834         case RENDERPATH_SOFT:
6835         case RENDERPATH_GLES2:
6836                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6837                 {
6838                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6839                         {
6840                                 // build GLSL gamma texture
6841 #define RAMPWIDTH 256
6842                                 unsigned short ramp[RAMPWIDTH * 3];
6843                                 unsigned char rampbgr[RAMPWIDTH][4];
6844                                 int i;
6845
6846                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6847
6848                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6849                                 for(i = 0; i < RAMPWIDTH; ++i)
6850                                 {
6851                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6852                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6853                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6854                                         rampbgr[i][3] = 0;
6855                                 }
6856                                 if (r_texture_gammaramps)
6857                                 {
6858                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6859                                 }
6860                                 else
6861                                 {
6862                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6863                                 }
6864                         }
6865                 }
6866                 else
6867                 {
6868                         // remove GLSL gamma texture
6869                 }
6870                 break;
6871         case RENDERPATH_GL11:
6872         case RENDERPATH_GL13:
6873         case RENDERPATH_GLES1:
6874                 break;
6875         }
6876 }
6877
6878 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6879 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6880 /*
6881 ================
6882 R_SelectScene
6883 ================
6884 */
6885 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6886         if( scenetype != r_currentscenetype ) {
6887                 // store the old scenetype
6888                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6889                 r_currentscenetype = scenetype;
6890                 // move in the new scene
6891                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6892         }
6893 }
6894
6895 /*
6896 ================
6897 R_GetScenePointer
6898 ================
6899 */
6900 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6901 {
6902         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6903         if( scenetype == r_currentscenetype ) {
6904                 return &r_refdef.scene;
6905         } else {
6906                 return &r_scenes_store[ scenetype ];
6907         }
6908 }
6909
6910 static int R_SortEntities_Compare(const void *ap, const void *bp)
6911 {
6912         const entity_render_t *a = *(const entity_render_t **)ap;
6913         const entity_render_t *b = *(const entity_render_t **)bp;
6914
6915         // 1. compare model
6916         if(a->model < b->model)
6917                 return -1;
6918         if(a->model > b->model)
6919                 return +1;
6920
6921         // 2. compare skin
6922         // TODO possibly calculate the REAL skinnum here first using
6923         // skinscenes?
6924         if(a->skinnum < b->skinnum)
6925                 return -1;
6926         if(a->skinnum > b->skinnum)
6927                 return +1;
6928
6929         // everything we compared is equal
6930         return 0;
6931 }
6932 static void R_SortEntities(void)
6933 {
6934         // below or equal 2 ents, sorting never gains anything
6935         if(r_refdef.scene.numentities <= 2)
6936                 return;
6937         // sort
6938         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6939 }
6940
6941 /*
6942 ================
6943 R_RenderView
6944 ================
6945 */
6946 int dpsoftrast_test;
6947 extern cvar_t r_shadow_bouncegrid;
6948 void R_RenderView(void)
6949 {
6950         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6951         int fbo;
6952         rtexture_t *depthtexture;
6953         rtexture_t *colortexture;
6954
6955         dpsoftrast_test = r_test.integer;
6956
6957         if (r_timereport_active)
6958                 R_TimeReport("start");
6959         r_textureframe++; // used only by R_GetCurrentTexture
6960         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6961
6962         if(R_CompileShader_CheckStaticParms())
6963                 R_GLSL_Restart_f();
6964
6965         if (!r_drawentities.integer)
6966                 r_refdef.scene.numentities = 0;
6967         else if (r_sortentities.integer)
6968                 R_SortEntities();
6969
6970         R_AnimCache_ClearCache();
6971         R_FrameData_NewFrame();
6972
6973         /* adjust for stereo display */
6974         if(R_Stereo_Active())
6975         {
6976                 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);
6977                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6978         }
6979
6980         if (r_refdef.view.isoverlay)
6981         {
6982                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6983                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6984                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6985                 R_TimeReport("depthclear");
6986
6987                 r_refdef.view.showdebug = false;
6988
6989                 r_fb.water.enabled = false;
6990                 r_fb.water.numwaterplanes = 0;
6991
6992                 R_RenderScene(0, NULL, NULL);
6993
6994                 r_refdef.view.matrix = originalmatrix;
6995
6996                 CHECKGLERROR
6997                 return;
6998         }
6999
7000         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7001         {
7002                 r_refdef.view.matrix = originalmatrix;
7003                 return;
7004         }
7005
7006         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7007
7008         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7009                 // in sRGB fallback, behave similar to true sRGB: convert this
7010                 // value from linear to sRGB
7011                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7012
7013         R_RenderView_UpdateViewVectors();
7014
7015         R_Shadow_UpdateWorldLightSelection();
7016
7017         R_Bloom_StartFrame();
7018
7019         // apply bloom brightness offset
7020         if(r_fb.bloomtexture[0])
7021                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7022
7023         R_Water_StartFrame();
7024
7025         // now we probably have an fbo to render into
7026         fbo = r_fb.fbo;
7027         depthtexture = r_fb.depthtexture;
7028         colortexture = r_fb.colortexture;
7029
7030         CHECKGLERROR
7031         if (r_timereport_active)
7032                 R_TimeReport("viewsetup");
7033
7034         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7035
7036         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7037         {
7038                 R_ClearScreen(r_refdef.fogenabled);
7039                 if (r_timereport_active)
7040                         R_TimeReport("viewclear");
7041         }
7042         r_refdef.view.clear = true;
7043
7044         r_refdef.view.showdebug = true;
7045
7046         R_View_Update();
7047         if (r_timereport_active)
7048                 R_TimeReport("visibility");
7049
7050         R_AnimCache_CacheVisibleEntities();
7051         if (r_timereport_active)
7052                 R_TimeReport("animcache");
7053
7054         R_Shadow_UpdateBounceGridTexture();
7055         if (r_timereport_active && r_shadow_bouncegrid.integer)
7056                 R_TimeReport("bouncegrid");
7057
7058         r_fb.water.numwaterplanes = 0;
7059         if (r_fb.water.enabled)
7060                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7061
7062         R_RenderScene(fbo, depthtexture, colortexture);
7063         r_fb.water.numwaterplanes = 0;
7064
7065         R_BlendView(fbo, depthtexture, colortexture);
7066         if (r_timereport_active)
7067                 R_TimeReport("blendview");
7068
7069         GL_Scissor(0, 0, vid.width, vid.height);
7070         GL_ScissorTest(false);
7071
7072         r_refdef.view.matrix = originalmatrix;
7073
7074         CHECKGLERROR
7075 }
7076
7077 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7078 {
7079         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7080         {
7081                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7082                 if (r_timereport_active)
7083                         R_TimeReport("waterworld");
7084         }
7085
7086         // don't let sound skip if going slow
7087         if (r_refdef.scene.extraupdate)
7088                 S_ExtraUpdate ();
7089
7090         R_DrawModelsAddWaterPlanes();
7091         if (r_timereport_active)
7092                 R_TimeReport("watermodels");
7093
7094         if (r_fb.water.numwaterplanes)
7095         {
7096                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7097                 if (r_timereport_active)
7098                         R_TimeReport("waterscenes");
7099         }
7100 }
7101
7102 extern cvar_t cl_locs_show;
7103 static void R_DrawLocs(void);
7104 static void R_DrawEntityBBoxes(void);
7105 static void R_DrawModelDecals(void);
7106 extern cvar_t cl_decals_newsystem;
7107 extern qboolean r_shadow_usingdeferredprepass;
7108 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7109 {
7110         qboolean shadowmapping = false;
7111
7112         if (r_timereport_active)
7113                 R_TimeReport("beginscene");
7114
7115         r_refdef.stats.renders++;
7116
7117         R_UpdateFog();
7118
7119         // don't let sound skip if going slow
7120         if (r_refdef.scene.extraupdate)
7121                 S_ExtraUpdate ();
7122
7123         R_MeshQueue_BeginScene();
7124
7125         R_SkyStartFrame();
7126
7127         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);
7128
7129         if (r_timereport_active)
7130                 R_TimeReport("skystartframe");
7131
7132         if (cl.csqc_vidvars.drawworld)
7133         {
7134                 // don't let sound skip if going slow
7135                 if (r_refdef.scene.extraupdate)
7136                         S_ExtraUpdate ();
7137
7138                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7139                 {
7140                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7141                         if (r_timereport_active)
7142                                 R_TimeReport("worldsky");
7143                 }
7144
7145                 if (R_DrawBrushModelsSky() && r_timereport_active)
7146                         R_TimeReport("bmodelsky");
7147
7148                 if (skyrendermasked && skyrenderlater)
7149                 {
7150                         // we have to force off the water clipping plane while rendering sky
7151                         R_SetupView(false, fbo, depthtexture, colortexture);
7152                         R_Sky();
7153                         R_SetupView(true, fbo, depthtexture, colortexture);
7154                         if (r_timereport_active)
7155                                 R_TimeReport("sky");
7156                 }
7157         }
7158
7159         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7160         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7161                 R_Shadow_PrepareModelShadows();
7162         if (r_timereport_active)
7163                 R_TimeReport("preparelights");
7164
7165         if (R_Shadow_ShadowMappingEnabled())
7166                 shadowmapping = true;
7167
7168         if (r_shadow_usingdeferredprepass)
7169                 R_Shadow_DrawPrepass();
7170
7171         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7172         {
7173                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7174                 if (r_timereport_active)
7175                         R_TimeReport("worlddepth");
7176         }
7177         if (r_depthfirst.integer >= 2)
7178         {
7179                 R_DrawModelsDepth();
7180                 if (r_timereport_active)
7181                         R_TimeReport("modeldepth");
7182         }
7183
7184         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7185         {
7186                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7187                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7188                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7189                 // don't let sound skip if going slow
7190                 if (r_refdef.scene.extraupdate)
7191                         S_ExtraUpdate ();
7192         }
7193
7194         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7195         {
7196                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7197                 if (r_timereport_active)
7198                         R_TimeReport("world");
7199         }
7200
7201         // don't let sound skip if going slow
7202         if (r_refdef.scene.extraupdate)
7203                 S_ExtraUpdate ();
7204
7205         R_DrawModels();
7206         if (r_timereport_active)
7207                 R_TimeReport("models");
7208
7209         // don't let sound skip if going slow
7210         if (r_refdef.scene.extraupdate)
7211                 S_ExtraUpdate ();
7212
7213         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7214         {
7215                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7216                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7217                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7218                 // don't let sound skip if going slow
7219                 if (r_refdef.scene.extraupdate)
7220                         S_ExtraUpdate ();
7221         }
7222
7223         if (!r_shadow_usingdeferredprepass)
7224         {
7225                 R_Shadow_DrawLights();
7226                 if (r_timereport_active)
7227                         R_TimeReport("rtlights");
7228         }
7229
7230         // don't let sound skip if going slow
7231         if (r_refdef.scene.extraupdate)
7232                 S_ExtraUpdate ();
7233
7234         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7235         {
7236                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7237                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7238                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7239                 // don't let sound skip if going slow
7240                 if (r_refdef.scene.extraupdate)
7241                         S_ExtraUpdate ();
7242         }
7243
7244         if (cl.csqc_vidvars.drawworld)
7245         {
7246                 if (cl_decals_newsystem.integer)
7247                 {
7248                         R_DrawModelDecals();
7249                         if (r_timereport_active)
7250                                 R_TimeReport("modeldecals");
7251                 }
7252                 else
7253                 {
7254                         R_DrawDecals();
7255                         if (r_timereport_active)
7256                                 R_TimeReport("decals");
7257                 }
7258
7259                 R_DrawParticles();
7260                 if (r_timereport_active)
7261                         R_TimeReport("particles");
7262
7263                 R_DrawExplosions();
7264                 if (r_timereport_active)
7265                         R_TimeReport("explosions");
7266
7267                 R_DrawLightningBeams();
7268                 if (r_timereport_active)
7269                         R_TimeReport("lightning");
7270         }
7271
7272         if (cl.csqc_loaded)
7273                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7274
7275         if (r_refdef.view.showdebug)
7276         {
7277                 if (cl_locs_show.integer)
7278                 {
7279                         R_DrawLocs();
7280                         if (r_timereport_active)
7281                                 R_TimeReport("showlocs");
7282                 }
7283
7284                 if (r_drawportals.integer)
7285                 {
7286                         R_DrawPortals();
7287                         if (r_timereport_active)
7288                                 R_TimeReport("portals");
7289                 }
7290
7291                 if (r_showbboxes.value > 0)
7292                 {
7293                         R_DrawEntityBBoxes();
7294                         if (r_timereport_active)
7295                                 R_TimeReport("bboxes");
7296                 }
7297         }
7298
7299         if (r_transparent.integer)
7300         {
7301                 R_MeshQueue_RenderTransparent();
7302                 if (r_timereport_active)
7303                         R_TimeReport("drawtrans");
7304         }
7305
7306         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))
7307         {
7308                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7309                 if (r_timereport_active)
7310                         R_TimeReport("worlddebug");
7311                 R_DrawModelsDebug();
7312                 if (r_timereport_active)
7313                         R_TimeReport("modeldebug");
7314         }
7315
7316         if (cl.csqc_vidvars.drawworld)
7317         {
7318                 R_Shadow_DrawCoronas();
7319                 if (r_timereport_active)
7320                         R_TimeReport("coronas");
7321         }
7322
7323 #if 0
7324         {
7325                 GL_DepthTest(false);
7326                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7327                 GL_Color(1, 1, 1, 1);
7328                 qglBegin(GL_POLYGON);
7329                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7330                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7331                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7332                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7333                 qglEnd();
7334                 qglBegin(GL_POLYGON);
7335                 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]);
7336                 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]);
7337                 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]);
7338                 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]);
7339                 qglEnd();
7340                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7341         }
7342 #endif
7343
7344         // don't let sound skip if going slow
7345         if (r_refdef.scene.extraupdate)
7346                 S_ExtraUpdate ();
7347 }
7348
7349 static const unsigned short bboxelements[36] =
7350 {
7351         5, 1, 3, 5, 3, 7,
7352         6, 2, 0, 6, 0, 4,
7353         7, 3, 2, 7, 2, 6,
7354         4, 0, 1, 4, 1, 5,
7355         4, 5, 7, 4, 7, 6,
7356         1, 0, 2, 1, 2, 3,
7357 };
7358
7359 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7360 {
7361         int i;
7362         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7363
7364         RSurf_ActiveWorldEntity();
7365
7366         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7367         GL_DepthMask(false);
7368         GL_DepthRange(0, 1);
7369         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7370 //      R_Mesh_ResetTextureState();
7371
7372         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7373         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7374         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7375         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7376         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7377         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7378         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7379         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7380         R_FillColors(color4f, 8, cr, cg, cb, ca);
7381         if (r_refdef.fogenabled)
7382         {
7383                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7384                 {
7385                         f1 = RSurf_FogVertex(v);
7386                         f2 = 1 - f1;
7387                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7388                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7389                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7390                 }
7391         }
7392         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7393         R_Mesh_ResetTextureState();
7394         R_SetupShader_Generic_NoTexture(false, false);
7395         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7396 }
7397
7398 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7399 {
7400         prvm_prog_t *prog = SVVM_prog;
7401         int i;
7402         float color[4];
7403         prvm_edict_t *edict;
7404
7405         // this function draws bounding boxes of server entities
7406         if (!sv.active)
7407                 return;
7408
7409         GL_CullFace(GL_NONE);
7410         R_SetupShader_Generic_NoTexture(false, false);
7411
7412         for (i = 0;i < numsurfaces;i++)
7413         {
7414                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7415                 switch ((int)PRVM_serveredictfloat(edict, solid))
7416                 {
7417                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7418                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7419                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7420                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7421                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7422                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7423                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7424                 }
7425                 color[3] *= r_showbboxes.value;
7426                 color[3] = bound(0, color[3], 1);
7427                 GL_DepthTest(!r_showdisabledepthtest.integer);
7428                 GL_CullFace(r_refdef.view.cullface_front);
7429                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7430         }
7431 }
7432
7433 static void R_DrawEntityBBoxes(void)
7434 {
7435         int i;
7436         prvm_edict_t *edict;
7437         vec3_t center;
7438         prvm_prog_t *prog = SVVM_prog;
7439
7440         // this function draws bounding boxes of server entities
7441         if (!sv.active)
7442                 return;
7443
7444         for (i = 0;i < prog->num_edicts;i++)
7445         {
7446                 edict = PRVM_EDICT_NUM(i);
7447                 if (edict->priv.server->free)
7448                         continue;
7449                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7450                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7451                         continue;
7452                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7453                         continue;
7454                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7455                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7456         }
7457 }
7458
7459 static const int nomodelelement3i[24] =
7460 {
7461         5, 2, 0,
7462         5, 1, 2,
7463         5, 0, 3,
7464         5, 3, 1,
7465         0, 2, 4,
7466         2, 1, 4,
7467         3, 0, 4,
7468         1, 3, 4
7469 };
7470
7471 static const unsigned short nomodelelement3s[24] =
7472 {
7473         5, 2, 0,
7474         5, 1, 2,
7475         5, 0, 3,
7476         5, 3, 1,
7477         0, 2, 4,
7478         2, 1, 4,
7479         3, 0, 4,
7480         1, 3, 4
7481 };
7482
7483 static const float nomodelvertex3f[6*3] =
7484 {
7485         -16,   0,   0,
7486          16,   0,   0,
7487           0, -16,   0,
7488           0,  16,   0,
7489           0,   0, -16,
7490           0,   0,  16
7491 };
7492
7493 static const float nomodelcolor4f[6*4] =
7494 {
7495         0.0f, 0.0f, 0.5f, 1.0f,
7496         0.0f, 0.0f, 0.5f, 1.0f,
7497         0.0f, 0.5f, 0.0f, 1.0f,
7498         0.0f, 0.5f, 0.0f, 1.0f,
7499         0.5f, 0.0f, 0.0f, 1.0f,
7500         0.5f, 0.0f, 0.0f, 1.0f
7501 };
7502
7503 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7504 {
7505         int i;
7506         float f1, f2, *c;
7507         float color4f[6*4];
7508
7509         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);
7510
7511         // this is only called once per entity so numsurfaces is always 1, and
7512         // surfacelist is always {0}, so this code does not handle batches
7513
7514         if (rsurface.ent_flags & RENDER_ADDITIVE)
7515         {
7516                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7517                 GL_DepthMask(false);
7518         }
7519         else if (rsurface.colormod[3] < 1)
7520         {
7521                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7522                 GL_DepthMask(false);
7523         }
7524         else
7525         {
7526                 GL_BlendFunc(GL_ONE, GL_ZERO);
7527                 GL_DepthMask(true);
7528         }
7529         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7530         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7531         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7532         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7533         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7534         for (i = 0, c = color4f;i < 6;i++, c += 4)
7535         {
7536                 c[0] *= rsurface.colormod[0];
7537                 c[1] *= rsurface.colormod[1];
7538                 c[2] *= rsurface.colormod[2];
7539                 c[3] *= rsurface.colormod[3];
7540         }
7541         if (r_refdef.fogenabled)
7542         {
7543                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7544                 {
7545                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7546                         f2 = 1 - f1;
7547                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7548                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7549                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7550                 }
7551         }
7552 //      R_Mesh_ResetTextureState();
7553         R_SetupShader_Generic_NoTexture(false, false);
7554         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7555         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7556 }
7557
7558 void R_DrawNoModel(entity_render_t *ent)
7559 {
7560         vec3_t org;
7561         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7562         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7563                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7564         else
7565                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7566 }
7567
7568 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7569 {
7570         vec3_t right1, right2, diff, normal;
7571
7572         VectorSubtract (org2, org1, normal);
7573
7574         // calculate 'right' vector for start
7575         VectorSubtract (r_refdef.view.origin, org1, diff);
7576         CrossProduct (normal, diff, right1);
7577         VectorNormalize (right1);
7578
7579         // calculate 'right' vector for end
7580         VectorSubtract (r_refdef.view.origin, org2, diff);
7581         CrossProduct (normal, diff, right2);
7582         VectorNormalize (right2);
7583
7584         vert[ 0] = org1[0] + width * right1[0];
7585         vert[ 1] = org1[1] + width * right1[1];
7586         vert[ 2] = org1[2] + width * right1[2];
7587         vert[ 3] = org1[0] - width * right1[0];
7588         vert[ 4] = org1[1] - width * right1[1];
7589         vert[ 5] = org1[2] - width * right1[2];
7590         vert[ 6] = org2[0] - width * right2[0];
7591         vert[ 7] = org2[1] - width * right2[1];
7592         vert[ 8] = org2[2] - width * right2[2];
7593         vert[ 9] = org2[0] + width * right2[0];
7594         vert[10] = org2[1] + width * right2[1];
7595         vert[11] = org2[2] + width * right2[2];
7596 }
7597
7598 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)
7599 {
7600         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7601         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7602         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7603         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7604         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7605         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7606         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7607         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7608         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7609         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7610         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7611         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7612 }
7613
7614 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7615 {
7616         int i;
7617         float *vertex3f;
7618         float v[3];
7619         VectorSet(v, x, y, z);
7620         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7621                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7622                         break;
7623         if (i == mesh->numvertices)
7624         {
7625                 if (mesh->numvertices < mesh->maxvertices)
7626                 {
7627                         VectorCopy(v, vertex3f);
7628                         mesh->numvertices++;
7629                 }
7630                 return mesh->numvertices;
7631         }
7632         else
7633                 return i;
7634 }
7635
7636 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7637 {
7638         int i;
7639         int *e, element[3];
7640         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7641         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7642         e = mesh->element3i + mesh->numtriangles * 3;
7643         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7644         {
7645                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7646                 if (mesh->numtriangles < mesh->maxtriangles)
7647                 {
7648                         *e++ = element[0];
7649                         *e++ = element[1];
7650                         *e++ = element[2];
7651                         mesh->numtriangles++;
7652                 }
7653                 element[1] = element[2];
7654         }
7655 }
7656
7657 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7658 {
7659         int i;
7660         int *e, element[3];
7661         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7662         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7663         e = mesh->element3i + mesh->numtriangles * 3;
7664         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7665         {
7666                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7667                 if (mesh->numtriangles < mesh->maxtriangles)
7668                 {
7669                         *e++ = element[0];
7670                         *e++ = element[1];
7671                         *e++ = element[2];
7672                         mesh->numtriangles++;
7673                 }
7674                 element[1] = element[2];
7675         }
7676 }
7677
7678 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7679 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7680 {
7681         int planenum, planenum2;
7682         int w;
7683         int tempnumpoints;
7684         mplane_t *plane, *plane2;
7685         double maxdist;
7686         double temppoints[2][256*3];
7687         // figure out how large a bounding box we need to properly compute this brush
7688         maxdist = 0;
7689         for (w = 0;w < numplanes;w++)
7690                 maxdist = max(maxdist, fabs(planes[w].dist));
7691         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7692         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7693         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7694         {
7695                 w = 0;
7696                 tempnumpoints = 4;
7697                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7698                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7699                 {
7700                         if (planenum2 == planenum)
7701                                 continue;
7702                         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);
7703                         w = !w;
7704                 }
7705                 if (tempnumpoints < 3)
7706                         continue;
7707                 // generate elements forming a triangle fan for this polygon
7708                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7709         }
7710 }
7711
7712 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)
7713 {
7714         texturelayer_t *layer;
7715         layer = t->currentlayers + t->currentnumlayers++;
7716         layer->type = type;
7717         layer->depthmask = depthmask;
7718         layer->blendfunc1 = blendfunc1;
7719         layer->blendfunc2 = blendfunc2;
7720         layer->texture = texture;
7721         layer->texmatrix = *matrix;
7722         layer->color[0] = r;
7723         layer->color[1] = g;
7724         layer->color[2] = b;
7725         layer->color[3] = a;
7726 }
7727
7728 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7729 {
7730         if(parms[0] == 0 && parms[1] == 0)
7731                 return false;
7732         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7733                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7734                         return false;
7735         return true;
7736 }
7737
7738 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7739 {
7740         double index, f;
7741         index = parms[2] + rsurface.shadertime * parms[3];
7742         index -= floor(index);
7743         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7744         {
7745         default:
7746         case Q3WAVEFUNC_NONE:
7747         case Q3WAVEFUNC_NOISE:
7748         case Q3WAVEFUNC_COUNT:
7749                 f = 0;
7750                 break;
7751         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7752         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7753         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7754         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7755         case Q3WAVEFUNC_TRIANGLE:
7756                 index *= 4;
7757                 f = index - floor(index);
7758                 if (index < 1)
7759                 {
7760                         // f = f;
7761                 }
7762                 else if (index < 2)
7763                         f = 1 - f;
7764                 else if (index < 3)
7765                         f = -f;
7766                 else
7767                         f = -(1 - f);
7768                 break;
7769         }
7770         f = parms[0] + parms[1] * f;
7771         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7772                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7773         return (float) f;
7774 }
7775
7776 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7777 {
7778         int w, h, idx;
7779         double f;
7780         double offsetd[2];
7781         float tcmat[12];
7782         matrix4x4_t matrix, temp;
7783         switch(tcmod->tcmod)
7784         {
7785                 case Q3TCMOD_COUNT:
7786                 case Q3TCMOD_NONE:
7787                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7788                                 matrix = r_waterscrollmatrix;
7789                         else
7790                                 matrix = identitymatrix;
7791                         break;
7792                 case Q3TCMOD_ENTITYTRANSLATE:
7793                         // this is used in Q3 to allow the gamecode to control texcoord
7794                         // scrolling on the entity, which is not supported in darkplaces yet.
7795                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7796                         break;
7797                 case Q3TCMOD_ROTATE:
7798                         f = tcmod->parms[0] * rsurface.shadertime;
7799                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7800                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7801                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7802                         break;
7803                 case Q3TCMOD_SCALE:
7804                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7805                         break;
7806                 case Q3TCMOD_SCROLL:
7807                         // extra care is needed because of precision breakdown with large values of time
7808                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7809                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7810                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7811                         break;
7812                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7813                         w = (int) tcmod->parms[0];
7814                         h = (int) tcmod->parms[1];
7815                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7816                         f = f - floor(f);
7817                         idx = (int) floor(f * w * h);
7818                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7819                         break;
7820                 case Q3TCMOD_STRETCH:
7821                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7822                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7823                         break;
7824                 case Q3TCMOD_TRANSFORM:
7825                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7826                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7827                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7828                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7829                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7830                         break;
7831                 case Q3TCMOD_TURBULENT:
7832                         // this is handled in the RSurf_PrepareVertices function
7833                         matrix = identitymatrix;
7834                         break;
7835         }
7836         temp = *texmatrix;
7837         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7838 }
7839
7840 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7841 {
7842         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7843         char name[MAX_QPATH];
7844         skinframe_t *skinframe;
7845         unsigned char pixels[296*194];
7846         strlcpy(cache->name, skinname, sizeof(cache->name));
7847         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7848         if (developer_loading.integer)
7849                 Con_Printf("loading %s\n", name);
7850         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7851         if (!skinframe || !skinframe->base)
7852         {
7853                 unsigned char *f;
7854                 fs_offset_t filesize;
7855                 skinframe = NULL;
7856                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7857                 if (f)
7858                 {
7859                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7860                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7861                         Mem_Free(f);
7862                 }
7863         }
7864         cache->skinframe = skinframe;
7865 }
7866
7867 texture_t *R_GetCurrentTexture(texture_t *t)
7868 {
7869         int i;
7870         const entity_render_t *ent = rsurface.entity;
7871         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7872         q3shaderinfo_layer_tcmod_t *tcmod;
7873
7874         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7875                 return t->currentframe;
7876         t->update_lastrenderframe = r_textureframe;
7877         t->update_lastrenderentity = (void *)ent;
7878
7879         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7880                 t->camera_entity = ent->entitynumber;
7881         else
7882                 t->camera_entity = 0;
7883
7884         // switch to an alternate material if this is a q1bsp animated material
7885         {
7886                 texture_t *texture = t;
7887                 int s = rsurface.ent_skinnum;
7888                 if ((unsigned int)s >= (unsigned int)model->numskins)
7889                         s = 0;
7890                 if (model->skinscenes)
7891                 {
7892                         if (model->skinscenes[s].framecount > 1)
7893                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7894                         else
7895                                 s = model->skinscenes[s].firstframe;
7896                 }
7897                 if (s > 0)
7898                         t = t + s * model->num_surfaces;
7899                 if (t->animated)
7900                 {
7901                         // use an alternate animation if the entity's frame is not 0,
7902                         // and only if the texture has an alternate animation
7903                         if (rsurface.ent_alttextures && t->anim_total[1])
7904                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7905                         else
7906                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7907                 }
7908                 texture->currentframe = t;
7909         }
7910
7911         // update currentskinframe to be a qw skin or animation frame
7912         if (rsurface.ent_qwskin >= 0)
7913         {
7914                 i = rsurface.ent_qwskin;
7915                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7916                 {
7917                         r_qwskincache_size = cl.maxclients;
7918                         if (r_qwskincache)
7919                                 Mem_Free(r_qwskincache);
7920                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7921                 }
7922                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7923                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7924                 t->currentskinframe = r_qwskincache[i].skinframe;
7925                 if (t->currentskinframe == NULL)
7926                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7927         }
7928         else if (t->numskinframes >= 2)
7929                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7930         if (t->backgroundnumskinframes >= 2)
7931                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7932
7933         t->currentmaterialflags = t->basematerialflags;
7934         t->currentalpha = rsurface.colormod[3];
7935         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7936                 t->currentalpha *= r_wateralpha.value;
7937         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7938                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7939         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7940                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7941         if (!(rsurface.ent_flags & RENDER_LIGHT))
7942                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7943         else if (FAKELIGHT_ENABLED)
7944         {
7945                 // no modellight if using fakelight for the map
7946         }
7947         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7948         {
7949                 // pick a model lighting mode
7950                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7951                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7952                 else
7953                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7954         }
7955         if (rsurface.ent_flags & RENDER_ADDITIVE)
7956                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7957         else if (t->currentalpha < 1)
7958                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7959         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7960         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7961                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7962         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7963                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7964         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7965                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7966         if (t->backgroundnumskinframes)
7967                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7968         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7969         {
7970                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7971                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7972         }
7973         else
7974                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7975         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7976         {
7977                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7978                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7979         }
7980         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7981                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7982
7983         // there is no tcmod
7984         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7985         {
7986                 t->currenttexmatrix = r_waterscrollmatrix;
7987                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7988         }
7989         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7990         {
7991                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7992                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7993         }
7994
7995         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7996                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7997         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7998                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7999
8000         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8001         if (t->currentskinframe->qpixels)
8002                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8003         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8004         if (!t->basetexture)
8005                 t->basetexture = r_texture_notexture;
8006         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8007         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8008         t->nmaptexture = t->currentskinframe->nmap;
8009         if (!t->nmaptexture)
8010                 t->nmaptexture = r_texture_blanknormalmap;
8011         t->glosstexture = r_texture_black;
8012         t->glowtexture = t->currentskinframe->glow;
8013         t->fogtexture = t->currentskinframe->fog;
8014         t->reflectmasktexture = t->currentskinframe->reflect;
8015         if (t->backgroundnumskinframes)
8016         {
8017                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8018                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8019                 t->backgroundglosstexture = r_texture_black;
8020                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8021                 if (!t->backgroundnmaptexture)
8022                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8023                 // make sure that if glow is going to be used, both textures are not NULL
8024                 if (!t->backgroundglowtexture && t->glowtexture)
8025                         t->backgroundglowtexture = r_texture_black;
8026                 if (!t->glowtexture && t->backgroundglowtexture)
8027                         t->glowtexture = r_texture_black;
8028         }
8029         else
8030         {
8031                 t->backgroundbasetexture = r_texture_white;
8032                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8033                 t->backgroundglosstexture = r_texture_black;
8034                 t->backgroundglowtexture = NULL;
8035         }
8036         t->specularpower = r_shadow_glossexponent.value;
8037         // TODO: store reference values for these in the texture?
8038         t->specularscale = 0;
8039         if (r_shadow_gloss.integer > 0)
8040         {
8041                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8042                 {
8043                         if (r_shadow_glossintensity.value > 0)
8044                         {
8045                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8046                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8047                                 t->specularscale = r_shadow_glossintensity.value;
8048                         }
8049                 }
8050                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8051                 {
8052                         t->glosstexture = r_texture_white;
8053                         t->backgroundglosstexture = r_texture_white;
8054                         t->specularscale = r_shadow_gloss2intensity.value;
8055                         t->specularpower = r_shadow_gloss2exponent.value;
8056                 }
8057         }
8058         t->specularscale *= t->specularscalemod;
8059         t->specularpower *= t->specularpowermod;
8060         t->rtlightambient = 0;
8061
8062         // lightmaps mode looks bad with dlights using actual texturing, so turn
8063         // off the colormap and glossmap, but leave the normalmap on as it still
8064         // accurately represents the shading involved
8065         if (gl_lightmaps.integer)
8066         {
8067                 t->basetexture = r_texture_grey128;
8068                 t->pantstexture = r_texture_black;
8069                 t->shirttexture = r_texture_black;
8070                 if (gl_lightmaps.integer < 2)
8071                         t->nmaptexture = r_texture_blanknormalmap;
8072                 t->glosstexture = r_texture_black;
8073                 t->glowtexture = NULL;
8074                 t->fogtexture = NULL;
8075                 t->reflectmasktexture = NULL;
8076                 t->backgroundbasetexture = NULL;
8077                 if (gl_lightmaps.integer < 2)
8078                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8079                 t->backgroundglosstexture = r_texture_black;
8080                 t->backgroundglowtexture = NULL;
8081                 t->specularscale = 0;
8082                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8083         }
8084
8085         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8086         VectorClear(t->dlightcolor);
8087         t->currentnumlayers = 0;
8088         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8089         {
8090                 int blendfunc1, blendfunc2;
8091                 qboolean depthmask;
8092                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8093                 {
8094                         blendfunc1 = GL_SRC_ALPHA;
8095                         blendfunc2 = GL_ONE;
8096                 }
8097                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8098                 {
8099                         blendfunc1 = GL_SRC_ALPHA;
8100                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8101                 }
8102                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8103                 {
8104                         blendfunc1 = t->customblendfunc[0];
8105                         blendfunc2 = t->customblendfunc[1];
8106                 }
8107                 else
8108                 {
8109                         blendfunc1 = GL_ONE;
8110                         blendfunc2 = GL_ZERO;
8111                 }
8112                 // don't colormod evilblend textures
8113                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8114                         VectorSet(t->lightmapcolor, 1, 1, 1);
8115                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8116                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8117                 {
8118                         // fullbright is not affected by r_refdef.lightmapintensity
8119                         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]);
8120                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8121                                 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]);
8122                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8123                                 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]);
8124                 }
8125                 else
8126                 {
8127                         vec3_t ambientcolor;
8128                         float colorscale;
8129                         // set the color tint used for lights affecting this surface
8130                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8131                         colorscale = 2;
8132                         // q3bsp has no lightmap updates, so the lightstylevalue that
8133                         // would normally be baked into the lightmap must be
8134                         // applied to the color
8135                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8136                         if (model->type == mod_brushq3)
8137                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8138                         colorscale *= r_refdef.lightmapintensity;
8139                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8140                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8141                         // basic lit geometry
8142                         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]);
8143                         // add pants/shirt if needed
8144                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8145                                 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]);
8146                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8147                                 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]);
8148                         // now add ambient passes if needed
8149                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8150                         {
8151                                 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]);
8152                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8153                                         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]);
8154                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8155                                         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]);
8156                         }
8157                 }
8158                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8159                         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]);
8160                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8161                 {
8162                         // if this is opaque use alpha blend which will darken the earlier
8163                         // passes cheaply.
8164                         //
8165                         // if this is an alpha blended material, all the earlier passes
8166                         // were darkened by fog already, so we only need to add the fog
8167                         // color ontop through the fog mask texture
8168                         //
8169                         // if this is an additive blended material, all the earlier passes
8170                         // were darkened by fog already, and we should not add fog color
8171                         // (because the background was not darkened, there is no fog color
8172                         // that was lost behind it).
8173                         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]);
8174                 }
8175         }
8176
8177         return t->currentframe;
8178 }
8179
8180 rsurfacestate_t rsurface;
8181
8182 void RSurf_ActiveWorldEntity(void)
8183 {
8184         dp_model_t *model = r_refdef.scene.worldmodel;
8185         //if (rsurface.entity == r_refdef.scene.worldentity)
8186         //      return;
8187         rsurface.entity = r_refdef.scene.worldentity;
8188         rsurface.skeleton = NULL;
8189         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8190         rsurface.ent_skinnum = 0;
8191         rsurface.ent_qwskin = -1;
8192         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8193         rsurface.shadertime = r_refdef.scene.time;
8194         rsurface.matrix = identitymatrix;
8195         rsurface.inversematrix = identitymatrix;
8196         rsurface.matrixscale = 1;
8197         rsurface.inversematrixscale = 1;
8198         R_EntityMatrix(&identitymatrix);
8199         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8200         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8201         rsurface.fograngerecip = r_refdef.fograngerecip;
8202         rsurface.fogheightfade = r_refdef.fogheightfade;
8203         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8204         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8205         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8206         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8207         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8208         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8209         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8210         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8211         rsurface.colormod[3] = 1;
8212         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);
8213         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8214         rsurface.frameblend[0].lerp = 1;
8215         rsurface.ent_alttextures = false;
8216         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8217         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8218         rsurface.entityskeletaltransform3x4 = NULL;
8219         rsurface.entityskeletalnumtransforms = 0;
8220         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8221         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8222         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8223         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8224         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8225         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8226         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8227         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8228         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8229         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8230         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8231         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8232         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8233         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8234         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8235         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8236         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8237         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8238         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8239         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8240         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8241         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8242         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8243         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8244         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8245         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8246         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8247         rsurface.modelelement3i = model->surfmesh.data_element3i;
8248         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8249         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8250         rsurface.modelelement3s = model->surfmesh.data_element3s;
8251         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8252         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8253         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8254         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8255         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8256         rsurface.modelsurfaces = model->data_surfaces;
8257         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8258         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8259         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8260         rsurface.modelgeneratedvertex = false;
8261         rsurface.batchgeneratedvertex = false;
8262         rsurface.batchfirstvertex = 0;
8263         rsurface.batchnumvertices = 0;
8264         rsurface.batchfirsttriangle = 0;
8265         rsurface.batchnumtriangles = 0;
8266         rsurface.batchvertex3f  = NULL;
8267         rsurface.batchvertex3f_vertexbuffer = NULL;
8268         rsurface.batchvertex3f_bufferoffset = 0;
8269         rsurface.batchsvector3f = NULL;
8270         rsurface.batchsvector3f_vertexbuffer = NULL;
8271         rsurface.batchsvector3f_bufferoffset = 0;
8272         rsurface.batchtvector3f = NULL;
8273         rsurface.batchtvector3f_vertexbuffer = NULL;
8274         rsurface.batchtvector3f_bufferoffset = 0;
8275         rsurface.batchnormal3f  = NULL;
8276         rsurface.batchnormal3f_vertexbuffer = NULL;
8277         rsurface.batchnormal3f_bufferoffset = 0;
8278         rsurface.batchlightmapcolor4f = NULL;
8279         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8280         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8281         rsurface.batchtexcoordtexture2f = NULL;
8282         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8283         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8284         rsurface.batchtexcoordlightmap2f = NULL;
8285         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8286         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8287         rsurface.batchskeletalindex4ub = NULL;
8288         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8289         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8290         rsurface.batchskeletalweight4ub = NULL;
8291         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8292         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8293         rsurface.batchvertexmesh = NULL;
8294         rsurface.batchvertexmeshbuffer = NULL;
8295         rsurface.batchvertex3fbuffer = NULL;
8296         rsurface.batchelement3i = NULL;
8297         rsurface.batchelement3i_indexbuffer = NULL;
8298         rsurface.batchelement3i_bufferoffset = 0;
8299         rsurface.batchelement3s = NULL;
8300         rsurface.batchelement3s_indexbuffer = NULL;
8301         rsurface.batchelement3s_bufferoffset = 0;
8302         rsurface.passcolor4f = NULL;
8303         rsurface.passcolor4f_vertexbuffer = NULL;
8304         rsurface.passcolor4f_bufferoffset = 0;
8305         rsurface.forcecurrenttextureupdate = false;
8306 }
8307
8308 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8309 {
8310         dp_model_t *model = ent->model;
8311         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8312         //      return;
8313         rsurface.entity = (entity_render_t *)ent;
8314         rsurface.skeleton = ent->skeleton;
8315         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8316         rsurface.ent_skinnum = ent->skinnum;
8317         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;
8318         rsurface.ent_flags = ent->flags;
8319         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8320         rsurface.matrix = ent->matrix;
8321         rsurface.inversematrix = ent->inversematrix;
8322         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8323         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8324         R_EntityMatrix(&rsurface.matrix);
8325         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8326         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8327         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8328         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8329         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8330         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8331         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8332         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8333         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8334         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8335         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8336         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8337         rsurface.colormod[3] = ent->alpha;
8338         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8339         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8340         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8341         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8342         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8343         if (ent->model->brush.submodel && !prepass)
8344         {
8345                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8346                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8347         }
8348         // if the animcache code decided it should use the shader path, skip the deform step
8349         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8350         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8351         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8352         {
8353                 if (ent->animcache_vertex3f)
8354                 {
8355                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8356                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8357                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8358                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8359                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8360                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8361                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8362                 }
8363                 else if (wanttangents)
8364                 {
8365                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8366                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8367                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8368                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8369                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8370                         rsurface.modelvertexmesh = NULL;
8371                         rsurface.modelvertexmeshbuffer = NULL;
8372                         rsurface.modelvertex3fbuffer = NULL;
8373                 }
8374                 else if (wantnormals)
8375                 {
8376                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8377                         rsurface.modelsvector3f = NULL;
8378                         rsurface.modeltvector3f = NULL;
8379                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8380                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8381                         rsurface.modelvertexmesh = NULL;
8382                         rsurface.modelvertexmeshbuffer = NULL;
8383                         rsurface.modelvertex3fbuffer = NULL;
8384                 }
8385                 else
8386                 {
8387                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8388                         rsurface.modelsvector3f = NULL;
8389                         rsurface.modeltvector3f = NULL;
8390                         rsurface.modelnormal3f = NULL;
8391                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8392                         rsurface.modelvertexmesh = NULL;
8393                         rsurface.modelvertexmeshbuffer = NULL;
8394                         rsurface.modelvertex3fbuffer = NULL;
8395                 }
8396                 rsurface.modelvertex3f_vertexbuffer = 0;
8397                 rsurface.modelvertex3f_bufferoffset = 0;
8398                 rsurface.modelsvector3f_vertexbuffer = 0;
8399                 rsurface.modelsvector3f_bufferoffset = 0;
8400                 rsurface.modeltvector3f_vertexbuffer = 0;
8401                 rsurface.modeltvector3f_bufferoffset = 0;
8402                 rsurface.modelnormal3f_vertexbuffer = 0;
8403                 rsurface.modelnormal3f_bufferoffset = 0;
8404                 rsurface.modelgeneratedvertex = true;
8405         }
8406         else
8407         {
8408                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8409                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8410                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8411                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8412                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8413                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8414                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8415                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8416                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8417                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8418                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8419                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8420                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8421                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8422                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8423                 rsurface.modelgeneratedvertex = false;
8424         }
8425         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8426         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8427         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8428         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8429         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8430         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8431         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8432         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8433         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8434         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8435         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8436         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8437         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8438         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8439         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8440         rsurface.modelelement3i = model->surfmesh.data_element3i;
8441         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8442         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8443         rsurface.modelelement3s = model->surfmesh.data_element3s;
8444         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8445         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8446         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8447         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8448         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8449         rsurface.modelsurfaces = model->data_surfaces;
8450         rsurface.batchgeneratedvertex = false;
8451         rsurface.batchfirstvertex = 0;
8452         rsurface.batchnumvertices = 0;
8453         rsurface.batchfirsttriangle = 0;
8454         rsurface.batchnumtriangles = 0;
8455         rsurface.batchvertex3f  = NULL;
8456         rsurface.batchvertex3f_vertexbuffer = NULL;
8457         rsurface.batchvertex3f_bufferoffset = 0;
8458         rsurface.batchsvector3f = NULL;
8459         rsurface.batchsvector3f_vertexbuffer = NULL;
8460         rsurface.batchsvector3f_bufferoffset = 0;
8461         rsurface.batchtvector3f = NULL;
8462         rsurface.batchtvector3f_vertexbuffer = NULL;
8463         rsurface.batchtvector3f_bufferoffset = 0;
8464         rsurface.batchnormal3f  = NULL;
8465         rsurface.batchnormal3f_vertexbuffer = NULL;
8466         rsurface.batchnormal3f_bufferoffset = 0;
8467         rsurface.batchlightmapcolor4f = NULL;
8468         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8469         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8470         rsurface.batchtexcoordtexture2f = NULL;
8471         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8472         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8473         rsurface.batchtexcoordlightmap2f = NULL;
8474         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8475         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8476         rsurface.batchskeletalindex4ub = NULL;
8477         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8478         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8479         rsurface.batchskeletalweight4ub = NULL;
8480         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8481         rsurface.batchskeletalweight4ub_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 = false;
8495 }
8496
8497 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)
8498 {
8499         rsurface.entity = r_refdef.scene.worldentity;
8500         rsurface.skeleton = NULL;
8501         rsurface.ent_skinnum = 0;
8502         rsurface.ent_qwskin = -1;
8503         rsurface.ent_flags = entflags;
8504         rsurface.shadertime = r_refdef.scene.time - shadertime;
8505         rsurface.modelnumvertices = numvertices;
8506         rsurface.modelnumtriangles = numtriangles;
8507         rsurface.matrix = *matrix;
8508         rsurface.inversematrix = *inversematrix;
8509         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8510         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8511         R_EntityMatrix(&rsurface.matrix);
8512         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8513         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8514         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8515         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8516         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8517         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8518         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8519         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8520         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8521         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8522         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8523         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8524         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);
8525         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8526         rsurface.frameblend[0].lerp = 1;
8527         rsurface.ent_alttextures = false;
8528         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8529         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8530         rsurface.entityskeletaltransform3x4 = NULL;
8531         rsurface.entityskeletalnumtransforms = 0;
8532         if (wanttangents)
8533         {
8534                 rsurface.modelvertex3f = (float *)vertex3f;
8535                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8536                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8537                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8538         }
8539         else if (wantnormals)
8540         {
8541                 rsurface.modelvertex3f = (float *)vertex3f;
8542                 rsurface.modelsvector3f = NULL;
8543                 rsurface.modeltvector3f = NULL;
8544                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8545         }
8546         else
8547         {
8548                 rsurface.modelvertex3f = (float *)vertex3f;
8549                 rsurface.modelsvector3f = NULL;
8550                 rsurface.modeltvector3f = NULL;
8551                 rsurface.modelnormal3f = NULL;
8552         }
8553         rsurface.modelvertexmesh = NULL;
8554         rsurface.modelvertexmeshbuffer = NULL;
8555         rsurface.modelvertex3fbuffer = NULL;
8556         rsurface.modelvertex3f_vertexbuffer = 0;
8557         rsurface.modelvertex3f_bufferoffset = 0;
8558         rsurface.modelsvector3f_vertexbuffer = 0;
8559         rsurface.modelsvector3f_bufferoffset = 0;
8560         rsurface.modeltvector3f_vertexbuffer = 0;
8561         rsurface.modeltvector3f_bufferoffset = 0;
8562         rsurface.modelnormal3f_vertexbuffer = 0;
8563         rsurface.modelnormal3f_bufferoffset = 0;
8564         rsurface.modelgeneratedvertex = true;
8565         rsurface.modellightmapcolor4f  = (float *)color4f;
8566         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8567         rsurface.modellightmapcolor4f_bufferoffset = 0;
8568         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8569         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8570         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8571         rsurface.modeltexcoordlightmap2f  = NULL;
8572         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8573         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8574         rsurface.modelskeletalindex4ub = NULL;
8575         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8576         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8577         rsurface.modelskeletalweight4ub = NULL;
8578         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8579         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8580         rsurface.modelelement3i = (int *)element3i;
8581         rsurface.modelelement3i_indexbuffer = NULL;
8582         rsurface.modelelement3i_bufferoffset = 0;
8583         rsurface.modelelement3s = (unsigned short *)element3s;
8584         rsurface.modelelement3s_indexbuffer = NULL;
8585         rsurface.modelelement3s_bufferoffset = 0;
8586         rsurface.modellightmapoffsets = NULL;
8587         rsurface.modelsurfaces = NULL;
8588         rsurface.batchgeneratedvertex = false;
8589         rsurface.batchfirstvertex = 0;
8590         rsurface.batchnumvertices = 0;
8591         rsurface.batchfirsttriangle = 0;
8592         rsurface.batchnumtriangles = 0;
8593         rsurface.batchvertex3f  = NULL;
8594         rsurface.batchvertex3f_vertexbuffer = NULL;
8595         rsurface.batchvertex3f_bufferoffset = 0;
8596         rsurface.batchsvector3f = NULL;
8597         rsurface.batchsvector3f_vertexbuffer = NULL;
8598         rsurface.batchsvector3f_bufferoffset = 0;
8599         rsurface.batchtvector3f = NULL;
8600         rsurface.batchtvector3f_vertexbuffer = NULL;
8601         rsurface.batchtvector3f_bufferoffset = 0;
8602         rsurface.batchnormal3f  = NULL;
8603         rsurface.batchnormal3f_vertexbuffer = NULL;
8604         rsurface.batchnormal3f_bufferoffset = 0;
8605         rsurface.batchlightmapcolor4f = NULL;
8606         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8607         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8608         rsurface.batchtexcoordtexture2f = NULL;
8609         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8610         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8611         rsurface.batchtexcoordlightmap2f = NULL;
8612         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8613         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8614         rsurface.batchskeletalindex4ub = NULL;
8615         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8616         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8617         rsurface.batchskeletalweight4ub = NULL;
8618         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8619         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8620         rsurface.batchvertexmesh = NULL;
8621         rsurface.batchvertexmeshbuffer = NULL;
8622         rsurface.batchvertex3fbuffer = NULL;
8623         rsurface.batchelement3i = NULL;
8624         rsurface.batchelement3i_indexbuffer = NULL;
8625         rsurface.batchelement3i_bufferoffset = 0;
8626         rsurface.batchelement3s = NULL;
8627         rsurface.batchelement3s_indexbuffer = NULL;
8628         rsurface.batchelement3s_bufferoffset = 0;
8629         rsurface.passcolor4f = NULL;
8630         rsurface.passcolor4f_vertexbuffer = NULL;
8631         rsurface.passcolor4f_bufferoffset = 0;
8632         rsurface.forcecurrenttextureupdate = true;
8633
8634         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8635         {
8636                 if ((wantnormals || wanttangents) && !normal3f)
8637                 {
8638                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8639                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8640                 }
8641                 if (wanttangents && !svector3f)
8642                 {
8643                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8644                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8645                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8646                 }
8647         }
8648 }
8649
8650 float RSurf_FogPoint(const float *v)
8651 {
8652         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8653         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8654         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8655         float FogHeightFade = r_refdef.fogheightfade;
8656         float fogfrac;
8657         unsigned int fogmasktableindex;
8658         if (r_refdef.fogplaneviewabove)
8659                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8660         else
8661                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8662         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8663         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8664 }
8665
8666 float RSurf_FogVertex(const float *v)
8667 {
8668         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8669         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8670         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8671         float FogHeightFade = rsurface.fogheightfade;
8672         float fogfrac;
8673         unsigned int fogmasktableindex;
8674         if (r_refdef.fogplaneviewabove)
8675                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8676         else
8677                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8678         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8679         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8680 }
8681
8682 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8683 {
8684         int i;
8685         for (i = 0;i < numelements;i++)
8686                 outelement3i[i] = inelement3i[i] + adjust;
8687 }
8688
8689 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8690 extern cvar_t gl_vbo;
8691 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8692 {
8693         int deformindex;
8694         int firsttriangle;
8695         int numtriangles;
8696         int firstvertex;
8697         int endvertex;
8698         int numvertices;
8699         int surfacefirsttriangle;
8700         int surfacenumtriangles;
8701         int surfacefirstvertex;
8702         int surfaceendvertex;
8703         int surfacenumvertices;
8704         int batchnumvertices;
8705         int batchnumtriangles;
8706         int needsupdate;
8707         int i, j;
8708         qboolean gaps;
8709         qboolean dynamicvertex;
8710         float amplitude;
8711         float animpos;
8712         float scale;
8713         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8714         float waveparms[4];
8715         unsigned char *ub;
8716         q3shaderinfo_deform_t *deform;
8717         const msurface_t *surface, *firstsurface;
8718         r_vertexmesh_t *vertexmesh;
8719         if (!texturenumsurfaces)
8720                 return;
8721         // find vertex range of this surface batch
8722         gaps = false;
8723         firstsurface = texturesurfacelist[0];
8724         firsttriangle = firstsurface->num_firsttriangle;
8725         batchnumvertices = 0;
8726         batchnumtriangles = 0;
8727         firstvertex = endvertex = firstsurface->num_firstvertex;
8728         for (i = 0;i < texturenumsurfaces;i++)
8729         {
8730                 surface = texturesurfacelist[i];
8731                 if (surface != firstsurface + i)
8732                         gaps = true;
8733                 surfacefirstvertex = surface->num_firstvertex;
8734                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8735                 surfacenumvertices = surface->num_vertices;
8736                 surfacenumtriangles = surface->num_triangles;
8737                 if (firstvertex > surfacefirstvertex)
8738                         firstvertex = surfacefirstvertex;
8739                 if (endvertex < surfaceendvertex)
8740                         endvertex = surfaceendvertex;
8741                 batchnumvertices += surfacenumvertices;
8742                 batchnumtriangles += surfacenumtriangles;
8743         }
8744
8745         // we now know the vertex range used, and if there are any gaps in it
8746         rsurface.batchfirstvertex = firstvertex;
8747         rsurface.batchnumvertices = endvertex - firstvertex;
8748         rsurface.batchfirsttriangle = firsttriangle;
8749         rsurface.batchnumtriangles = batchnumtriangles;
8750
8751         // this variable holds flags for which properties have been updated that
8752         // may require regenerating vertexmesh array...
8753         needsupdate = 0;
8754
8755         // check if any dynamic vertex processing must occur
8756         dynamicvertex = false;
8757
8758         // a cvar to force the dynamic vertex path to be taken, for debugging
8759         if (r_batch_debugdynamicvertexpath.integer)
8760                 dynamicvertex = true;
8761
8762         // if there is a chance of animated vertex colors, it's a dynamic batch
8763         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8764         {
8765                 dynamicvertex = true;
8766                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8767         }
8768
8769         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8770         {
8771                 switch (deform->deform)
8772                 {
8773                 default:
8774                 case Q3DEFORM_PROJECTIONSHADOW:
8775                 case Q3DEFORM_TEXT0:
8776                 case Q3DEFORM_TEXT1:
8777                 case Q3DEFORM_TEXT2:
8778                 case Q3DEFORM_TEXT3:
8779                 case Q3DEFORM_TEXT4:
8780                 case Q3DEFORM_TEXT5:
8781                 case Q3DEFORM_TEXT6:
8782                 case Q3DEFORM_TEXT7:
8783                 case Q3DEFORM_NONE:
8784                         break;
8785                 case Q3DEFORM_AUTOSPRITE:
8786                         dynamicvertex = true;
8787                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8788                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8789                         break;
8790                 case Q3DEFORM_AUTOSPRITE2:
8791                         dynamicvertex = true;
8792                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8793                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8794                         break;
8795                 case Q3DEFORM_NORMAL:
8796                         dynamicvertex = true;
8797                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8798                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8799                         break;
8800                 case Q3DEFORM_WAVE:
8801                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8802                                 break; // if wavefunc is a nop, ignore this transform
8803                         dynamicvertex = true;
8804                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8805                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8806                         break;
8807                 case Q3DEFORM_BULGE:
8808                         dynamicvertex = true;
8809                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8810                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8811                         break;
8812                 case Q3DEFORM_MOVE:
8813                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8814                                 break; // if wavefunc is a nop, ignore this transform
8815                         dynamicvertex = true;
8816                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8817                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8818                         break;
8819                 }
8820         }
8821         switch(rsurface.texture->tcgen.tcgen)
8822         {
8823         default:
8824         case Q3TCGEN_TEXTURE:
8825                 break;
8826         case Q3TCGEN_LIGHTMAP:
8827                 dynamicvertex = true;
8828                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8829                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8830                 break;
8831         case Q3TCGEN_VECTOR:
8832                 dynamicvertex = true;
8833                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8834                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8835                 break;
8836         case Q3TCGEN_ENVIRONMENT:
8837                 dynamicvertex = true;
8838                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8839                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8840                 break;
8841         }
8842         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8843         {
8844                 dynamicvertex = true;
8845                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8846                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8847         }
8848
8849         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8850         {
8851                 dynamicvertex = true;
8852                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8853         }
8854
8855         // when the model data has no vertex buffer (dynamic mesh), we need to
8856         // eliminate gaps
8857         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8858                 batchneed |= BATCHNEED_NOGAPS;
8859
8860         // the caller can specify BATCHNEED_NOGAPS to force a batch with
8861         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8862         // we ensure this by treating the vertex batch as dynamic...
8863         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8864                 dynamicvertex = true;
8865
8866         if (dynamicvertex)
8867         {
8868                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8869                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8870                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8871                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8872                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8873                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8874                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8875                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
8876         }
8877
8878         // if needsupdate, we have to do a dynamic vertex batch for sure
8879         if (needsupdate & batchneed)
8880                 dynamicvertex = true;
8881
8882         // see if we need to build vertexmesh from arrays
8883         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8884                 dynamicvertex = true;
8885
8886         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
8887         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
8888                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
8889
8890         rsurface.batchvertex3f = rsurface.modelvertex3f;
8891         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8892         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8893         rsurface.batchsvector3f = rsurface.modelsvector3f;
8894         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8895         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8896         rsurface.batchtvector3f = rsurface.modeltvector3f;
8897         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8898         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8899         rsurface.batchnormal3f = rsurface.modelnormal3f;
8900         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8901         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8902         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8903         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8904         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8905         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8906         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8907         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8908         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8909         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8910         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8911         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
8912         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
8913         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
8914         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
8915         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
8916         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
8917         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8918         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8919         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8920         rsurface.batchelement3i = rsurface.modelelement3i;
8921         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8922         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8923         rsurface.batchelement3s = rsurface.modelelement3s;
8924         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8925         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8926         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
8927         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
8928
8929         // if any dynamic vertex processing has to occur in software, we copy the
8930         // entire surface list together before processing to rebase the vertices
8931         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8932         //
8933         // if any gaps exist and we do not have a static vertex buffer, we have to
8934         // copy the surface list together to avoid wasting upload bandwidth on the
8935         // vertices in the gaps.
8936         //
8937         // if gaps exist and we have a static vertex buffer, we can choose whether
8938         // to combine the index buffer ranges into one dynamic index buffer or
8939         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8940         //
8941         // in many cases the batch is reduced to one draw call.
8942
8943         rsurface.batchmultidraw = false;
8944         rsurface.batchmultidrawnumsurfaces = 0;
8945         rsurface.batchmultidrawsurfacelist = NULL;
8946
8947         if (!dynamicvertex)
8948         {
8949                 // static vertex data, just set pointers...
8950                 rsurface.batchgeneratedvertex = false;
8951                 // if there are gaps, we want to build a combined index buffer,
8952                 // otherwise use the original static buffer with an appropriate offset
8953                 if (gaps)
8954                 {
8955                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
8956                         {
8957                                 rsurface.batchmultidraw = true;
8958                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
8959                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
8960                                 return;
8961                         }
8962                         // build a new triangle elements array for this batch
8963                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8964                         rsurface.batchfirsttriangle = 0;
8965                         numtriangles = 0;
8966                         for (i = 0;i < texturenumsurfaces;i++)
8967                         {
8968                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8969                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8970                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8971                                 numtriangles += surfacenumtriangles;
8972                         }
8973                         rsurface.batchelement3i_indexbuffer = NULL;
8974                         rsurface.batchelement3i_bufferoffset = 0;
8975                         rsurface.batchelement3s = NULL;
8976                         rsurface.batchelement3s_indexbuffer = NULL;
8977                         rsurface.batchelement3s_bufferoffset = 0;
8978                         if (endvertex <= 65536)
8979                         {
8980                                 // make a 16bit (unsigned short) index array if possible
8981                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8982                                 for (i = 0;i < numtriangles*3;i++)
8983                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8984                         }
8985                 }
8986                 return;
8987         }
8988
8989         // something needs software processing, do it for real...
8990         // we only directly handle separate array data in this case and then
8991         // generate interleaved data if needed...
8992         rsurface.batchgeneratedvertex = true;
8993
8994         // now copy the vertex data into a combined array and make an index array
8995         // (this is what Quake3 does all the time)
8996         // we also apply any skeletal animation here that would have been done in
8997         // the vertex shader, because most of the dynamic vertex animation cases
8998         // need actual vertex positions and normals
8999         //if (dynamicvertex)
9000         {
9001                 rsurface.batchvertex3fbuffer = NULL;
9002                 rsurface.batchvertexmesh = NULL;
9003                 rsurface.batchvertexmeshbuffer = NULL;
9004                 rsurface.batchvertex3f = NULL;
9005                 rsurface.batchvertex3f_vertexbuffer = NULL;
9006                 rsurface.batchvertex3f_bufferoffset = 0;
9007                 rsurface.batchsvector3f = NULL;
9008                 rsurface.batchsvector3f_vertexbuffer = NULL;
9009                 rsurface.batchsvector3f_bufferoffset = 0;
9010                 rsurface.batchtvector3f = NULL;
9011                 rsurface.batchtvector3f_vertexbuffer = NULL;
9012                 rsurface.batchtvector3f_bufferoffset = 0;
9013                 rsurface.batchnormal3f = NULL;
9014                 rsurface.batchnormal3f_vertexbuffer = NULL;
9015                 rsurface.batchnormal3f_bufferoffset = 0;
9016                 rsurface.batchlightmapcolor4f = NULL;
9017                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9018                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9019                 rsurface.batchtexcoordtexture2f = NULL;
9020                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9021                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9022                 rsurface.batchtexcoordlightmap2f = NULL;
9023                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9024                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9025                 rsurface.batchskeletalindex4ub = NULL;
9026                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9027                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9028                 rsurface.batchskeletalweight4ub = NULL;
9029                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9030                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9031                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9032                 rsurface.batchelement3i_indexbuffer = NULL;
9033                 rsurface.batchelement3i_bufferoffset = 0;
9034                 rsurface.batchelement3s = NULL;
9035                 rsurface.batchelement3s_indexbuffer = NULL;
9036                 rsurface.batchelement3s_bufferoffset = 0;
9037                 // we'll only be setting up certain arrays as needed
9038                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9039                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9040                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9041                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9042                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9043                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9044                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9045                 {
9046                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9047                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9048                 }
9049                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9050                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9051                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9052                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9053                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9054                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9055                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9056                 {
9057                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9058                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9059                 }
9060                 numvertices = 0;
9061                 numtriangles = 0;
9062                 for (i = 0;i < texturenumsurfaces;i++)
9063                 {
9064                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9065                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9066                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9067                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9068                         // copy only the data requested
9069                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9070                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9071                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9072                         {
9073                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9074                                 {
9075                                         if (rsurface.batchvertex3f)
9076                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9077                                         else
9078                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9079                                 }
9080                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9081                                 {
9082                                         if (rsurface.modelnormal3f)
9083                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9084                                         else
9085                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9086                                 }
9087                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9088                                 {
9089                                         if (rsurface.modelsvector3f)
9090                                         {
9091                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9092                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9093                                         }
9094                                         else
9095                                         {
9096                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9097                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9098                                         }
9099                                 }
9100                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9101                                 {
9102                                         if (rsurface.modellightmapcolor4f)
9103                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9104                                         else
9105                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9106                                 }
9107                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9108                                 {
9109                                         if (rsurface.modeltexcoordtexture2f)
9110                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9111                                         else
9112                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9113                                 }
9114                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9115                                 {
9116                                         if (rsurface.modeltexcoordlightmap2f)
9117                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9118                                         else
9119                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9120                                 }
9121                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9122                                 {
9123                                         if (rsurface.modelskeletalindex4ub)
9124                                         {
9125                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9126                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9127                                         }
9128                                         else
9129                                         {
9130                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9131                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9132                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9133                                                 for (j = 0;j < surfacenumvertices;j++)
9134                                                         ub[j*4] = 255;
9135                                         }
9136                                 }
9137                         }
9138                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9139                         numvertices += surfacenumvertices;
9140                         numtriangles += surfacenumtriangles;
9141                 }
9142
9143                 // generate a 16bit index array as well if possible
9144                 // (in general, dynamic batches fit)
9145                 if (numvertices <= 65536)
9146                 {
9147                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9148                         for (i = 0;i < numtriangles*3;i++)
9149                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9150                 }
9151
9152                 // since we've copied everything, the batch now starts at 0
9153                 rsurface.batchfirstvertex = 0;
9154                 rsurface.batchnumvertices = batchnumvertices;
9155                 rsurface.batchfirsttriangle = 0;
9156                 rsurface.batchnumtriangles = batchnumtriangles;
9157         }
9158
9159         // apply skeletal animation that would have been done in the vertex shader
9160         if (rsurface.batchskeletaltransform3x4)
9161         {
9162                 const unsigned char *si;
9163                 const unsigned char *sw;
9164                 const float *t[4];
9165                 const float *b = rsurface.batchskeletaltransform3x4;
9166                 float *vp, *vs, *vt, *vn;
9167                 float w[4];
9168                 float m[3][4], n[3][4];
9169                 float tp[3], ts[3], tt[3], tn[3];
9170                 si = rsurface.batchskeletalindex4ub;
9171                 sw = rsurface.batchskeletalweight4ub;
9172                 vp = rsurface.batchvertex3f;
9173                 vs = rsurface.batchsvector3f;
9174                 vt = rsurface.batchtvector3f;
9175                 vn = rsurface.batchnormal3f;
9176                 memset(m[0], 0, sizeof(m));
9177                 memset(n[0], 0, sizeof(n));
9178                 for (i = 0;i < batchnumvertices;i++)
9179                 {
9180                         t[0] = b + si[0]*12;
9181                         if (sw[0] == 255)
9182                         {
9183                                 // common case - only one matrix
9184                                 m[0][0] = t[0][ 0];
9185                                 m[0][1] = t[0][ 1];
9186                                 m[0][2] = t[0][ 2];
9187                                 m[0][3] = t[0][ 3];
9188                                 m[1][0] = t[0][ 4];
9189                                 m[1][1] = t[0][ 5];
9190                                 m[1][2] = t[0][ 6];
9191                                 m[1][3] = t[0][ 7];
9192                                 m[2][0] = t[0][ 8];
9193                                 m[2][1] = t[0][ 9];
9194                                 m[2][2] = t[0][10];
9195                                 m[2][3] = t[0][11];
9196                         }
9197                         else if (sw[2] + sw[3])
9198                         {
9199                                 // blend 4 matrices
9200                                 t[1] = b + si[1]*12;
9201                                 t[2] = b + si[2]*12;
9202                                 t[3] = b + si[3]*12;
9203                                 w[0] = sw[0] * (1.0f / 255.0f);
9204                                 w[1] = sw[1] * (1.0f / 255.0f);
9205                                 w[2] = sw[2] * (1.0f / 255.0f);
9206                                 w[3] = sw[3] * (1.0f / 255.0f);
9207                                 // blend the matrices
9208                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9209                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9210                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9211                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9212                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9213                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9214                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9215                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9216                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9217                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9218                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9219                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9220                         }
9221                         else
9222                         {
9223                                 // blend 2 matrices
9224                                 t[1] = b + si[1]*12;
9225                                 w[0] = sw[0] * (1.0f / 255.0f);
9226                                 w[1] = sw[1] * (1.0f / 255.0f);
9227                                 // blend the matrices
9228                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9229                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9230                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9231                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9232                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9233                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9234                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9235                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9236                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9237                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9238                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9239                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9240                         }
9241                         si += 4;
9242                         sw += 4;
9243                         // modify the vertex
9244                         VectorCopy(vp, tp);
9245                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9246                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9247                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9248                         vp += 3;
9249                         if (vn)
9250                         {
9251                                 // the normal transformation matrix is a set of cross products...
9252                                 CrossProduct(m[1], m[2], n[0]);
9253                                 CrossProduct(m[2], m[0], n[1]);
9254                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9255                                 VectorCopy(vn, tn);
9256                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9257                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9258                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9259                                 VectorNormalize(vn);
9260                                 vn += 3;
9261                                 if (vs)
9262                                 {
9263                                         VectorCopy(vs, ts);
9264                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9265                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9266                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9267                                         VectorNormalize(vs);
9268                                         vs += 3;
9269                                         VectorCopy(vt, tt);
9270                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9271                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9272                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9273                                         VectorNormalize(vt);
9274                                         vt += 3;
9275                                 }
9276                         }
9277                 }
9278                 rsurface.batchskeletaltransform3x4 = NULL;
9279                 rsurface.batchskeletalnumtransforms = 0;
9280         }
9281
9282         // q1bsp surfaces rendered in vertex color mode have to have colors
9283         // calculated based on lightstyles
9284         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9285         {
9286                 // generate color arrays for the surfaces in this list
9287                 int c[4];
9288                 int scale;
9289                 int size3;
9290                 const int *offsets;
9291                 const unsigned char *lm;
9292                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9293                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9294                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9295                 numvertices = 0;
9296                 for (i = 0;i < texturenumsurfaces;i++)
9297                 {
9298                         surface = texturesurfacelist[i];
9299                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9300                         surfacenumvertices = surface->num_vertices;
9301                         if (surface->lightmapinfo->samples)
9302                         {
9303                                 for (j = 0;j < surfacenumvertices;j++)
9304                                 {
9305                                         lm = surface->lightmapinfo->samples + offsets[j];
9306                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9307                                         VectorScale(lm, scale, c);
9308                                         if (surface->lightmapinfo->styles[1] != 255)
9309                                         {
9310                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9311                                                 lm += size3;
9312                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9313                                                 VectorMA(c, scale, lm, c);
9314                                                 if (surface->lightmapinfo->styles[2] != 255)
9315                                                 {
9316                                                         lm += size3;
9317                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9318                                                         VectorMA(c, scale, lm, c);
9319                                                         if (surface->lightmapinfo->styles[3] != 255)
9320                                                         {
9321                                                                 lm += size3;
9322                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9323                                                                 VectorMA(c, scale, lm, c);
9324                                                         }
9325                                                 }
9326                                         }
9327                                         c[0] >>= 7;
9328                                         c[1] >>= 7;
9329                                         c[2] >>= 7;
9330                                         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);
9331                                         numvertices++;
9332                                 }
9333                         }
9334                         else
9335                         {
9336                                 for (j = 0;j < surfacenumvertices;j++)
9337                                 {
9338                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9339                                         numvertices++;
9340                                 }
9341                         }
9342                 }
9343         }
9344
9345         // if vertices are deformed (sprite flares and things in maps, possibly
9346         // water waves, bulges and other deformations), modify the copied vertices
9347         // in place
9348         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9349         {
9350                 switch (deform->deform)
9351                 {
9352                 default:
9353                 case Q3DEFORM_PROJECTIONSHADOW:
9354                 case Q3DEFORM_TEXT0:
9355                 case Q3DEFORM_TEXT1:
9356                 case Q3DEFORM_TEXT2:
9357                 case Q3DEFORM_TEXT3:
9358                 case Q3DEFORM_TEXT4:
9359                 case Q3DEFORM_TEXT5:
9360                 case Q3DEFORM_TEXT6:
9361                 case Q3DEFORM_TEXT7:
9362                 case Q3DEFORM_NONE:
9363                         break;
9364                 case Q3DEFORM_AUTOSPRITE:
9365                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9366                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9367                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9368                         VectorNormalize(newforward);
9369                         VectorNormalize(newright);
9370                         VectorNormalize(newup);
9371 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9372 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9373 //                      rsurface.batchvertex3f_bufferoffset = 0;
9374 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9375 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9376 //                      rsurface.batchsvector3f_bufferoffset = 0;
9377 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9378 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9379 //                      rsurface.batchtvector3f_bufferoffset = 0;
9380 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9381 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9382 //                      rsurface.batchnormal3f_bufferoffset = 0;
9383                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9384                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9385                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9386                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9387                                 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);
9388                         // a single autosprite surface can contain multiple sprites...
9389                         for (j = 0;j < batchnumvertices - 3;j += 4)
9390                         {
9391                                 VectorClear(center);
9392                                 for (i = 0;i < 4;i++)
9393                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9394                                 VectorScale(center, 0.25f, center);
9395                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9396                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9397                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9398                                 for (i = 0;i < 4;i++)
9399                                 {
9400                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9401                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9402                                 }
9403                         }
9404                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9405                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9406                         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);
9407                         break;
9408                 case Q3DEFORM_AUTOSPRITE2:
9409                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9410                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9411                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9412                         VectorNormalize(newforward);
9413                         VectorNormalize(newright);
9414                         VectorNormalize(newup);
9415 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9416 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9417 //                      rsurface.batchvertex3f_bufferoffset = 0;
9418                         {
9419                                 const float *v1, *v2;
9420                                 vec3_t start, end;
9421                                 float f, l;
9422                                 struct
9423                                 {
9424                                         float length2;
9425                                         const float *v1;
9426                                         const float *v2;
9427                                 }
9428                                 shortest[2];
9429                                 memset(shortest, 0, sizeof(shortest));
9430                                 // a single autosprite surface can contain multiple sprites...
9431                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9432                                 {
9433                                         VectorClear(center);
9434                                         for (i = 0;i < 4;i++)
9435                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9436                                         VectorScale(center, 0.25f, center);
9437                                         // find the two shortest edges, then use them to define the
9438                                         // axis vectors for rotating around the central axis
9439                                         for (i = 0;i < 6;i++)
9440                                         {
9441                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9442                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9443                                                 l = VectorDistance2(v1, v2);
9444                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9445                                                 if (v1[2] != v2[2])
9446                                                         l += (1.0f / 1024.0f);
9447                                                 if (shortest[0].length2 > l || i == 0)
9448                                                 {
9449                                                         shortest[1] = shortest[0];
9450                                                         shortest[0].length2 = l;
9451                                                         shortest[0].v1 = v1;
9452                                                         shortest[0].v2 = v2;
9453                                                 }
9454                                                 else if (shortest[1].length2 > l || i == 1)
9455                                                 {
9456                                                         shortest[1].length2 = l;
9457                                                         shortest[1].v1 = v1;
9458                                                         shortest[1].v2 = v2;
9459                                                 }
9460                                         }
9461                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9462                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9463                                         // this calculates the right vector from the shortest edge
9464                                         // and the up vector from the edge midpoints
9465                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9466                                         VectorNormalize(right);
9467                                         VectorSubtract(end, start, up);
9468                                         VectorNormalize(up);
9469                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9470                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9471                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9472                                         VectorNegate(forward, forward);
9473                                         VectorReflect(forward, 0, up, forward);
9474                                         VectorNormalize(forward);
9475                                         CrossProduct(up, forward, newright);
9476                                         VectorNormalize(newright);
9477                                         // rotate the quad around the up axis vector, this is made
9478                                         // especially easy by the fact we know the quad is flat,
9479                                         // so we only have to subtract the center position and
9480                                         // measure distance along the right vector, and then
9481                                         // multiply that by the newright vector and add back the
9482                                         // center position
9483                                         // we also need to subtract the old position to undo the
9484                                         // displacement from the center, which we do with a
9485                                         // DotProduct, the subtraction/addition of center is also
9486                                         // optimized into DotProducts here
9487                                         l = DotProduct(right, center);
9488                                         for (i = 0;i < 4;i++)
9489                                         {
9490                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9491                                                 f = DotProduct(right, v1) - l;
9492                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9493                                         }
9494                                 }
9495                         }
9496                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9497                         {
9498 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9499 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9500 //                              rsurface.batchnormal3f_bufferoffset = 0;
9501                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9502                         }
9503                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9504                         {
9505 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9506 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9507 //                              rsurface.batchsvector3f_bufferoffset = 0;
9508 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9509 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9510 //                              rsurface.batchtvector3f_bufferoffset = 0;
9511                                 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);
9512                         }
9513                         break;
9514                 case Q3DEFORM_NORMAL:
9515                         // deform the normals to make reflections wavey
9516                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9517                         rsurface.batchnormal3f_vertexbuffer = NULL;
9518                         rsurface.batchnormal3f_bufferoffset = 0;
9519                         for (j = 0;j < batchnumvertices;j++)
9520                         {
9521                                 float vertex[3];
9522                                 float *normal = rsurface.batchnormal3f + 3*j;
9523                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9524                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9525                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9526                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9527                                 VectorNormalize(normal);
9528                         }
9529                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9530                         {
9531 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9532 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9533 //                              rsurface.batchsvector3f_bufferoffset = 0;
9534 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9535 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9536 //                              rsurface.batchtvector3f_bufferoffset = 0;
9537                                 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);
9538                         }
9539                         break;
9540                 case Q3DEFORM_WAVE:
9541                         // deform vertex array to make wavey water and flags and such
9542                         waveparms[0] = deform->waveparms[0];
9543                         waveparms[1] = deform->waveparms[1];
9544                         waveparms[2] = deform->waveparms[2];
9545                         waveparms[3] = deform->waveparms[3];
9546                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9547                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9548                         // this is how a divisor of vertex influence on deformation
9549                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9550                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9551 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9552 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9553 //                      rsurface.batchvertex3f_bufferoffset = 0;
9554 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9555 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9556 //                      rsurface.batchnormal3f_bufferoffset = 0;
9557                         for (j = 0;j < batchnumvertices;j++)
9558                         {
9559                                 // if the wavefunc depends on time, evaluate it per-vertex
9560                                 if (waveparms[3])
9561                                 {
9562                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9563                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9564                                 }
9565                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9566                         }
9567                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9568                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9569                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9570                         {
9571 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9572 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9573 //                              rsurface.batchsvector3f_bufferoffset = 0;
9574 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9575 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9576 //                              rsurface.batchtvector3f_bufferoffset = 0;
9577                                 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);
9578                         }
9579                         break;
9580                 case Q3DEFORM_BULGE:
9581                         // deform vertex array to make the surface have moving bulges
9582 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9583 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9584 //                      rsurface.batchvertex3f_bufferoffset = 0;
9585 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9586 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9587 //                      rsurface.batchnormal3f_bufferoffset = 0;
9588                         for (j = 0;j < batchnumvertices;j++)
9589                         {
9590                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9591                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9592                         }
9593                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9594                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9595                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9596                         {
9597 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9598 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9599 //                              rsurface.batchsvector3f_bufferoffset = 0;
9600 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9601 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9602 //                              rsurface.batchtvector3f_bufferoffset = 0;
9603                                 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);
9604                         }
9605                         break;
9606                 case Q3DEFORM_MOVE:
9607                         // deform vertex array
9608                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9609                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9610                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9611                         VectorScale(deform->parms, scale, waveparms);
9612 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9613 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9614 //                      rsurface.batchvertex3f_bufferoffset = 0;
9615                         for (j = 0;j < batchnumvertices;j++)
9616                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9617                         break;
9618                 }
9619         }
9620
9621         // generate texcoords based on the chosen texcoord source
9622         switch(rsurface.texture->tcgen.tcgen)
9623         {
9624         default:
9625         case Q3TCGEN_TEXTURE:
9626                 break;
9627         case Q3TCGEN_LIGHTMAP:
9628 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9629 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9630 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9631                 if (rsurface.batchtexcoordlightmap2f)
9632                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9633                 break;
9634         case Q3TCGEN_VECTOR:
9635 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9636 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9637 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9638                 for (j = 0;j < batchnumvertices;j++)
9639                 {
9640                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9641                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9642                 }
9643                 break;
9644         case Q3TCGEN_ENVIRONMENT:
9645                 // make environment reflections using a spheremap
9646                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9647                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9648                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9649                 for (j = 0;j < batchnumvertices;j++)
9650                 {
9651                         // identical to Q3A's method, but executed in worldspace so
9652                         // carried models can be shiny too
9653
9654                         float viewer[3], d, reflected[3], worldreflected[3];
9655
9656                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9657                         // VectorNormalize(viewer);
9658
9659                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9660
9661                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9662                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9663                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9664                         // note: this is proportinal to viewer, so we can normalize later
9665
9666                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9667                         VectorNormalize(worldreflected);
9668
9669                         // note: this sphere map only uses world x and z!
9670                         // so positive and negative y will LOOK THE SAME.
9671                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9672                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9673                 }
9674                 break;
9675         }
9676         // the only tcmod that needs software vertex processing is turbulent, so
9677         // check for it here and apply the changes if needed
9678         // and we only support that as the first one
9679         // (handling a mixture of turbulent and other tcmods would be problematic
9680         //  without punting it entirely to a software path)
9681         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9682         {
9683                 amplitude = rsurface.texture->tcmods[0].parms[1];
9684                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9685 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9686 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9687 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9688                 for (j = 0;j < batchnumvertices;j++)
9689                 {
9690                         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);
9691                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9692                 }
9693         }
9694
9695         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9696         {
9697                 // convert the modified arrays to vertex structs
9698 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9699 //              rsurface.batchvertexmeshbuffer = NULL;
9700                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9701                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9702                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9703                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9704                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9705                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9706                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9707                 {
9708                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9709                         {
9710                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9711                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9712                         }
9713                 }
9714                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9715                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9716                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9717                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9718                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9719                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9720                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9721                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9722                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9723                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9724                 {
9725                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9726                         {
9727                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9728                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9729                         }
9730                 }
9731         }
9732 }
9733
9734 void RSurf_DrawBatch(void)
9735 {
9736         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9737         // through the pipeline, killing it earlier in the pipeline would have
9738         // per-surface overhead rather than per-batch overhead, so it's best to
9739         // reject it here, before it hits glDraw.
9740         if (rsurface.batchnumtriangles == 0)
9741                 return;
9742 #if 0
9743         // batch debugging code
9744         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9745         {
9746                 int i;
9747                 int j;
9748                 int c;
9749                 const int *e;
9750                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9751                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9752                 {
9753                         c = e[i];
9754                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9755                         {
9756                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9757                                 {
9758                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9759                                                 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);
9760                                         break;
9761                                 }
9762                         }
9763                 }
9764         }
9765 #endif
9766         if (rsurface.batchmultidraw)
9767         {
9768                 // issue multiple draws rather than copying index data
9769                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9770                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9771                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9772                 for (i = 0;i < numsurfaces;)
9773                 {
9774                         // combine consecutive surfaces as one draw
9775                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9776                                 if (surfacelist[j] != surfacelist[k] + 1)
9777                                         break;
9778                         firstvertex = surfacelist[i]->num_firstvertex;
9779                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9780                         firsttriangle = surfacelist[i]->num_firsttriangle;
9781                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9782                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
9783                         i = j;
9784                 }
9785         }
9786         else
9787         {
9788                 // there is only one consecutive run of index data (may have been combined)
9789                 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);
9790         }
9791 }
9792
9793 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9794 {
9795         // pick the closest matching water plane
9796         int planeindex, vertexindex, bestplaneindex = -1;
9797         float d, bestd;
9798         vec3_t vert;
9799         const float *v;
9800         r_waterstate_waterplane_t *p;
9801         qboolean prepared = false;
9802         bestd = 0;
9803         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9804         {
9805                 if(p->camera_entity != rsurface.texture->camera_entity)
9806                         continue;
9807                 d = 0;
9808                 if(!prepared)
9809                 {
9810                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9811                         prepared = true;
9812                         if(rsurface.batchnumvertices == 0)
9813                                 break;
9814                 }
9815                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9816                 {
9817                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9818                         d += fabs(PlaneDiff(vert, &p->plane));
9819                 }
9820                 if (bestd > d || bestplaneindex < 0)
9821                 {
9822                         bestd = d;
9823                         bestplaneindex = planeindex;
9824                 }
9825         }
9826         return bestplaneindex;
9827         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9828         // this situation though, as it might be better to render single larger
9829         // batches with useless stuff (backface culled for example) than to
9830         // render multiple smaller batches
9831 }
9832
9833 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9834 {
9835         int i;
9836         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9837         rsurface.passcolor4f_vertexbuffer = 0;
9838         rsurface.passcolor4f_bufferoffset = 0;
9839         for (i = 0;i < rsurface.batchnumvertices;i++)
9840                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9841 }
9842
9843 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9844 {
9845         int i;
9846         float f;
9847         const float *v;
9848         const float *c;
9849         float *c2;
9850         if (rsurface.passcolor4f)
9851         {
9852                 // generate color arrays
9853                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9854                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9855                 rsurface.passcolor4f_vertexbuffer = 0;
9856                 rsurface.passcolor4f_bufferoffset = 0;
9857                 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)
9858                 {
9859                         f = RSurf_FogVertex(v);
9860                         c2[0] = c[0] * f;
9861                         c2[1] = c[1] * f;
9862                         c2[2] = c[2] * f;
9863                         c2[3] = c[3];
9864                 }
9865         }
9866         else
9867         {
9868                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9869                 rsurface.passcolor4f_vertexbuffer = 0;
9870                 rsurface.passcolor4f_bufferoffset = 0;
9871                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9872                 {
9873                         f = RSurf_FogVertex(v);
9874                         c2[0] = f;
9875                         c2[1] = f;
9876                         c2[2] = f;
9877                         c2[3] = 1;
9878                 }
9879         }
9880 }
9881
9882 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9883 {
9884         int i;
9885         float f;
9886         const float *v;
9887         const float *c;
9888         float *c2;
9889         if (!rsurface.passcolor4f)
9890                 return;
9891         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9892         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9893         rsurface.passcolor4f_vertexbuffer = 0;
9894         rsurface.passcolor4f_bufferoffset = 0;
9895         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)
9896         {
9897                 f = RSurf_FogVertex(v);
9898                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9899                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9900                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9901                 c2[3] = c[3];
9902         }
9903 }
9904
9905 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9906 {
9907         int i;
9908         const float *c;
9909         float *c2;
9910         if (!rsurface.passcolor4f)
9911                 return;
9912         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9913         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9914         rsurface.passcolor4f_vertexbuffer = 0;
9915         rsurface.passcolor4f_bufferoffset = 0;
9916         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9917         {
9918                 c2[0] = c[0] * r;
9919                 c2[1] = c[1] * g;
9920                 c2[2] = c[2] * b;
9921                 c2[3] = c[3] * a;
9922         }
9923 }
9924
9925 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9926 {
9927         int i;
9928         const float *c;
9929         float *c2;
9930         if (!rsurface.passcolor4f)
9931                 return;
9932         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9933         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9934         rsurface.passcolor4f_vertexbuffer = 0;
9935         rsurface.passcolor4f_bufferoffset = 0;
9936         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9937         {
9938                 c2[0] = c[0] + r_refdef.scene.ambient;
9939                 c2[1] = c[1] + r_refdef.scene.ambient;
9940                 c2[2] = c[2] + r_refdef.scene.ambient;
9941                 c2[3] = c[3];
9942         }
9943 }
9944
9945 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9946 {
9947         // TODO: optimize
9948         rsurface.passcolor4f = NULL;
9949         rsurface.passcolor4f_vertexbuffer = 0;
9950         rsurface.passcolor4f_bufferoffset = 0;
9951         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9952         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9953         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9954         GL_Color(r, g, b, a);
9955         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9956         RSurf_DrawBatch();
9957 }
9958
9959 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9960 {
9961         // TODO: optimize applyfog && applycolor case
9962         // just apply fog if necessary, and tint the fog color array if necessary
9963         rsurface.passcolor4f = NULL;
9964         rsurface.passcolor4f_vertexbuffer = 0;
9965         rsurface.passcolor4f_bufferoffset = 0;
9966         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9967         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9968         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9969         GL_Color(r, g, b, a);
9970         RSurf_DrawBatch();
9971 }
9972
9973 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9974 {
9975         // TODO: optimize
9976         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9977         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9978         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9979         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9980         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9981         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9982         GL_Color(r, g, b, a);
9983         RSurf_DrawBatch();
9984 }
9985
9986 static void RSurf_DrawBatch_GL11_ClampColor(void)
9987 {
9988         int i;
9989         const float *c1;
9990         float *c2;
9991         if (!rsurface.passcolor4f)
9992                 return;
9993         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9994         {
9995                 c2[0] = bound(0.0f, c1[0], 1.0f);
9996                 c2[1] = bound(0.0f, c1[1], 1.0f);
9997                 c2[2] = bound(0.0f, c1[2], 1.0f);
9998                 c2[3] = bound(0.0f, c1[3], 1.0f);
9999         }
10000 }
10001
10002 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10003 {
10004         int i;
10005         float f;
10006         const float *v;
10007         const float *n;
10008         float *c;
10009         //vec3_t eyedir;
10010
10011         // fake shading
10012         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10013         rsurface.passcolor4f_vertexbuffer = 0;
10014         rsurface.passcolor4f_bufferoffset = 0;
10015         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)
10016         {
10017                 f = -DotProduct(r_refdef.view.forward, n);
10018                 f = max(0, f);
10019                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10020                 f *= r_refdef.lightmapintensity;
10021                 Vector4Set(c, f, f, f, 1);
10022         }
10023 }
10024
10025 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10026 {
10027         RSurf_DrawBatch_GL11_ApplyFakeLight();
10028         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10029         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10030         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10031         GL_Color(r, g, b, a);
10032         RSurf_DrawBatch();
10033 }
10034
10035 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10036 {
10037         int i;
10038         float f;
10039         float alpha;
10040         const float *v;
10041         const float *n;
10042         float *c;
10043         vec3_t ambientcolor;
10044         vec3_t diffusecolor;
10045         vec3_t lightdir;
10046         // TODO: optimize
10047         // model lighting
10048         VectorCopy(rsurface.modellight_lightdir, lightdir);
10049         f = 0.5f * r_refdef.lightmapintensity;
10050         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10051         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10052         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10053         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10054         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10055         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10056         alpha = *a;
10057         if (VectorLength2(diffusecolor) > 0)
10058         {
10059                 // q3-style directional shading
10060                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10061                 rsurface.passcolor4f_vertexbuffer = 0;
10062                 rsurface.passcolor4f_bufferoffset = 0;
10063                 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)
10064                 {
10065                         if ((f = DotProduct(n, lightdir)) > 0)
10066                                 VectorMA(ambientcolor, f, diffusecolor, c);
10067                         else
10068                                 VectorCopy(ambientcolor, c);
10069                         c[3] = alpha;
10070                 }
10071                 *r = 1;
10072                 *g = 1;
10073                 *b = 1;
10074                 *a = 1;
10075                 *applycolor = false;
10076         }
10077         else
10078         {
10079                 *r = ambientcolor[0];
10080                 *g = ambientcolor[1];
10081                 *b = ambientcolor[2];
10082                 rsurface.passcolor4f = NULL;
10083                 rsurface.passcolor4f_vertexbuffer = 0;
10084                 rsurface.passcolor4f_bufferoffset = 0;
10085         }
10086 }
10087
10088 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10089 {
10090         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10091         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10092         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10093         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10094         GL_Color(r, g, b, a);
10095         RSurf_DrawBatch();
10096 }
10097
10098 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10099 {
10100         int i;
10101         float f;
10102         const float *v;
10103         float *c;
10104
10105         // fake shading
10106         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10107         rsurface.passcolor4f_vertexbuffer = 0;
10108         rsurface.passcolor4f_bufferoffset = 0;
10109
10110         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10111         {
10112                 f = 1 - RSurf_FogVertex(v);
10113                 c[0] = r;
10114                 c[1] = g;
10115                 c[2] = b;
10116                 c[3] = f * a;
10117         }
10118 }
10119
10120 void RSurf_SetupDepthAndCulling(void)
10121 {
10122         // submodels are biased to avoid z-fighting with world surfaces that they
10123         // may be exactly overlapping (avoids z-fighting artifacts on certain
10124         // doors and things in Quake maps)
10125         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10126         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10127         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10128         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10129 }
10130
10131 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10132 {
10133         // transparent sky would be ridiculous
10134         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10135                 return;
10136         R_SetupShader_Generic_NoTexture(false, false);
10137         skyrenderlater = true;
10138         RSurf_SetupDepthAndCulling();
10139         GL_DepthMask(true);
10140         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10141         // skymasking on them, and Quake3 never did sky masking (unlike
10142         // software Quake and software Quake2), so disable the sky masking
10143         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10144         // and skymasking also looks very bad when noclipping outside the
10145         // level, so don't use it then either.
10146         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10147         {
10148                 R_Mesh_ResetTextureState();
10149                 if (skyrendermasked)
10150                 {
10151                         R_SetupShader_DepthOrShadow(false, false, false);
10152                         // depth-only (masking)
10153                         GL_ColorMask(0,0,0,0);
10154                         // just to make sure that braindead drivers don't draw
10155                         // anything despite that colormask...
10156                         GL_BlendFunc(GL_ZERO, GL_ONE);
10157                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10158                         if (rsurface.batchvertex3fbuffer)
10159                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10160                         else
10161                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10162                 }
10163                 else
10164                 {
10165                         R_SetupShader_Generic_NoTexture(false, false);
10166                         // fog sky
10167                         GL_BlendFunc(GL_ONE, GL_ZERO);
10168                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10169                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10170                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10171                 }
10172                 RSurf_DrawBatch();
10173                 if (skyrendermasked)
10174                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10175         }
10176         R_Mesh_ResetTextureState();
10177         GL_Color(1, 1, 1, 1);
10178 }
10179
10180 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10181 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10182 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10183 {
10184         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10185                 return;
10186         if (prepass)
10187         {
10188                 // render screenspace normalmap to texture
10189                 GL_DepthMask(true);
10190                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10191                 RSurf_DrawBatch();
10192                 return;
10193         }
10194
10195         // bind lightmap texture
10196
10197         // water/refraction/reflection/camera surfaces have to be handled specially
10198         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10199         {
10200                 int start, end, startplaneindex;
10201                 for (start = 0;start < texturenumsurfaces;start = end)
10202                 {
10203                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10204                         if(startplaneindex < 0)
10205                         {
10206                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10207                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10208                                 end = start + 1;
10209                                 continue;
10210                         }
10211                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10212                                 ;
10213                         // now that we have a batch using the same planeindex, render it
10214                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10215                         {
10216                                 // render water or distortion background
10217                                 GL_DepthMask(true);
10218                                 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);
10219                                 RSurf_DrawBatch();
10220                                 // blend surface on top
10221                                 GL_DepthMask(false);
10222                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10223                                 RSurf_DrawBatch();
10224                         }
10225                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10226                         {
10227                                 // render surface with reflection texture as input
10228                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10229                                 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);
10230                                 RSurf_DrawBatch();
10231                         }
10232                 }
10233                 return;
10234         }
10235
10236         // render surface batch normally
10237         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10238         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);
10239         RSurf_DrawBatch();
10240 }
10241
10242 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10243 {
10244         // OpenGL 1.3 path - anything not completely ancient
10245         qboolean applycolor;
10246         qboolean applyfog;
10247         int layerindex;
10248         const texturelayer_t *layer;
10249         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);
10250         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10251
10252         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10253         {
10254                 vec4_t layercolor;
10255                 int layertexrgbscale;
10256                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10257                 {
10258                         if (layerindex == 0)
10259                                 GL_AlphaTest(true);
10260                         else
10261                         {
10262                                 GL_AlphaTest(false);
10263                                 GL_DepthFunc(GL_EQUAL);
10264                         }
10265                 }
10266                 GL_DepthMask(layer->depthmask && writedepth);
10267                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10268                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10269                 {
10270                         layertexrgbscale = 4;
10271                         VectorScale(layer->color, 0.25f, layercolor);
10272                 }
10273                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10274                 {
10275                         layertexrgbscale = 2;
10276                         VectorScale(layer->color, 0.5f, layercolor);
10277                 }
10278                 else
10279                 {
10280                         layertexrgbscale = 1;
10281                         VectorScale(layer->color, 1.0f, layercolor);
10282                 }
10283                 layercolor[3] = layer->color[3];
10284                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10285                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10286                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10287                 switch (layer->type)
10288                 {
10289                 case TEXTURELAYERTYPE_LITTEXTURE:
10290                         // single-pass lightmapped texture with 2x rgbscale
10291                         R_Mesh_TexBind(0, r_texture_white);
10292                         R_Mesh_TexMatrix(0, NULL);
10293                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10294                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10295                         R_Mesh_TexBind(1, layer->texture);
10296                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10297                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10298                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10299                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10300                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10301                         else if (FAKELIGHT_ENABLED)
10302                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10303                         else if (rsurface.uselightmaptexture)
10304                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10305                         else
10306                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10307                         break;
10308                 case TEXTURELAYERTYPE_TEXTURE:
10309                         // singletexture unlit texture with transparency support
10310                         R_Mesh_TexBind(0, layer->texture);
10311                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10312                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10313                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10314                         R_Mesh_TexBind(1, 0);
10315                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10316                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10317                         break;
10318                 case TEXTURELAYERTYPE_FOG:
10319                         // singletexture fogging
10320                         if (layer->texture)
10321                         {
10322                                 R_Mesh_TexBind(0, layer->texture);
10323                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10324                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10325                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10326                         }
10327                         else
10328                         {
10329                                 R_Mesh_TexBind(0, 0);
10330                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10331                         }
10332                         R_Mesh_TexBind(1, 0);
10333                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10334                         // generate a color array for the fog pass
10335                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10336                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10337                         RSurf_DrawBatch();
10338                         break;
10339                 default:
10340                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10341                 }
10342         }
10343         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10344         {
10345                 GL_DepthFunc(GL_LEQUAL);
10346                 GL_AlphaTest(false);
10347         }
10348 }
10349
10350 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10351 {
10352         // OpenGL 1.1 - crusty old voodoo path
10353         qboolean applyfog;
10354         int layerindex;
10355         const texturelayer_t *layer;
10356         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);
10357         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10358
10359         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10360         {
10361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10362                 {
10363                         if (layerindex == 0)
10364                                 GL_AlphaTest(true);
10365                         else
10366                         {
10367                                 GL_AlphaTest(false);
10368                                 GL_DepthFunc(GL_EQUAL);
10369                         }
10370                 }
10371                 GL_DepthMask(layer->depthmask && writedepth);
10372                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10373                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10374                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10375                 switch (layer->type)
10376                 {
10377                 case TEXTURELAYERTYPE_LITTEXTURE:
10378                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10379                         {
10380                                 // two-pass lit texture with 2x rgbscale
10381                                 // first the lightmap pass
10382                                 R_Mesh_TexBind(0, r_texture_white);
10383                                 R_Mesh_TexMatrix(0, NULL);
10384                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10385                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10386                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10387                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10388                                 else if (FAKELIGHT_ENABLED)
10389                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10390                                 else if (rsurface.uselightmaptexture)
10391                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10392                                 else
10393                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10394                                 // then apply the texture to it
10395                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10396                                 R_Mesh_TexBind(0, layer->texture);
10397                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10398                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10399                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10400                                 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);
10401                         }
10402                         else
10403                         {
10404                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10405                                 R_Mesh_TexBind(0, layer->texture);
10406                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10407                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10408                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10409                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10410                                         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);
10411                                 else if (FAKELIGHT_ENABLED)
10412                                         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);
10413                                 else
10414                                         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);
10415                         }
10416                         break;
10417                 case TEXTURELAYERTYPE_TEXTURE:
10418                         // singletexture unlit texture with transparency support
10419                         R_Mesh_TexBind(0, layer->texture);
10420                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10421                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10422                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10423                         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);
10424                         break;
10425                 case TEXTURELAYERTYPE_FOG:
10426                         // singletexture fogging
10427                         if (layer->texture)
10428                         {
10429                                 R_Mesh_TexBind(0, layer->texture);
10430                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10431                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10432                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10433                         }
10434                         else
10435                         {
10436                                 R_Mesh_TexBind(0, 0);
10437                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10438                         }
10439                         // generate a color array for the fog pass
10440                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10441                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10442                         RSurf_DrawBatch();
10443                         break;
10444                 default:
10445                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10446                 }
10447         }
10448         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10449         {
10450                 GL_DepthFunc(GL_LEQUAL);
10451                 GL_AlphaTest(false);
10452         }
10453 }
10454
10455 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10456 {
10457         int vi;
10458         int j;
10459         r_vertexgeneric_t *batchvertex;
10460         float c[4];
10461
10462 //      R_Mesh_ResetTextureState();
10463         R_SetupShader_Generic_NoTexture(false, false);
10464
10465         if(rsurface.texture && rsurface.texture->currentskinframe)
10466         {
10467                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10468                 c[3] *= rsurface.texture->currentalpha;
10469         }
10470         else
10471         {
10472                 c[0] = 1;
10473                 c[1] = 0;
10474                 c[2] = 1;
10475                 c[3] = 1;
10476         }
10477
10478         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10479         {
10480                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10481                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10482                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10483         }
10484
10485         // brighten it up (as texture value 127 means "unlit")
10486         c[0] *= 2 * r_refdef.view.colorscale;
10487         c[1] *= 2 * r_refdef.view.colorscale;
10488         c[2] *= 2 * r_refdef.view.colorscale;
10489
10490         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10491                 c[3] *= r_wateralpha.value;
10492
10493         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10494         {
10495                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10496                 GL_DepthMask(false);
10497         }
10498         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10499         {
10500                 GL_BlendFunc(GL_ONE, GL_ONE);
10501                 GL_DepthMask(false);
10502         }
10503         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10504         {
10505                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10506                 GL_DepthMask(false);
10507         }
10508         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10509         {
10510                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10511                 GL_DepthMask(false);
10512         }
10513         else
10514         {
10515                 GL_BlendFunc(GL_ONE, GL_ZERO);
10516                 GL_DepthMask(writedepth);
10517         }
10518
10519         if (r_showsurfaces.integer == 3)
10520         {
10521                 rsurface.passcolor4f = NULL;
10522
10523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10524                 {
10525                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10526
10527                         rsurface.passcolor4f = NULL;
10528                         rsurface.passcolor4f_vertexbuffer = 0;
10529                         rsurface.passcolor4f_bufferoffset = 0;
10530                 }
10531                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10532                 {
10533                         qboolean applycolor = true;
10534                         float one = 1.0;
10535
10536                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10537
10538                         r_refdef.lightmapintensity = 1;
10539                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10540                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10541                 }
10542                 else if (FAKELIGHT_ENABLED)
10543                 {
10544                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10545
10546                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10547                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10548                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10549                 }
10550                 else
10551                 {
10552                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10553
10554                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10555                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10556                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10557                 }
10558
10559                 if(!rsurface.passcolor4f)
10560                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10561
10562                 RSurf_DrawBatch_GL11_ApplyAmbient();
10563                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10564                 if(r_refdef.fogenabled)
10565                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10566                 RSurf_DrawBatch_GL11_ClampColor();
10567
10568                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10569                 R_SetupShader_Generic_NoTexture(false, false);
10570                 RSurf_DrawBatch();
10571         }
10572         else if (!r_refdef.view.showdebug)
10573         {
10574                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10575                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10576                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10577                 {
10578                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10579                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10580                 }
10581                 R_Mesh_PrepareVertices_Generic_Unlock();
10582                 RSurf_DrawBatch();
10583         }
10584         else if (r_showsurfaces.integer == 4)
10585         {
10586                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10587                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10588                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10589                 {
10590                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10591                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10592                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10593                 }
10594                 R_Mesh_PrepareVertices_Generic_Unlock();
10595                 RSurf_DrawBatch();
10596         }
10597         else if (r_showsurfaces.integer == 2)
10598         {
10599                 const int *e;
10600                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10601                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10602                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10603                 {
10604                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10605                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10606                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10607                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10608                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10609                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10610                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10611                 }
10612                 R_Mesh_PrepareVertices_Generic_Unlock();
10613                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10614         }
10615         else
10616         {
10617                 int texturesurfaceindex;
10618                 int k;
10619                 const msurface_t *surface;
10620                 float surfacecolor4f[4];
10621                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10622                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10623                 vi = 0;
10624                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10625                 {
10626                         surface = texturesurfacelist[texturesurfaceindex];
10627                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10628                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10629                         for (j = 0;j < surface->num_vertices;j++)
10630                         {
10631                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10632                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10633                                 vi++;
10634                         }
10635                 }
10636                 R_Mesh_PrepareVertices_Generic_Unlock();
10637                 RSurf_DrawBatch();
10638         }
10639 }
10640
10641 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10642 {
10643         CHECKGLERROR
10644         RSurf_SetupDepthAndCulling();
10645         if (r_showsurfaces.integer)
10646         {
10647                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10648                 return;
10649         }
10650         switch (vid.renderpath)
10651         {
10652         case RENDERPATH_GL20:
10653         case RENDERPATH_D3D9:
10654         case RENDERPATH_D3D10:
10655         case RENDERPATH_D3D11:
10656         case RENDERPATH_SOFT:
10657         case RENDERPATH_GLES2:
10658                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10659                 break;
10660         case RENDERPATH_GL13:
10661         case RENDERPATH_GLES1:
10662                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10663                 break;
10664         case RENDERPATH_GL11:
10665                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10666                 break;
10667         }
10668         CHECKGLERROR
10669 }
10670
10671 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10672 {
10673         CHECKGLERROR
10674         RSurf_SetupDepthAndCulling();
10675         if (r_showsurfaces.integer)
10676         {
10677                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10678                 return;
10679         }
10680         switch (vid.renderpath)
10681         {
10682         case RENDERPATH_GL20:
10683         case RENDERPATH_D3D9:
10684         case RENDERPATH_D3D10:
10685         case RENDERPATH_D3D11:
10686         case RENDERPATH_SOFT:
10687         case RENDERPATH_GLES2:
10688                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10689                 break;
10690         case RENDERPATH_GL13:
10691         case RENDERPATH_GLES1:
10692                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10693                 break;
10694         case RENDERPATH_GL11:
10695                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10696                 break;
10697         }
10698         CHECKGLERROR
10699 }
10700
10701 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10702 {
10703         int i, j;
10704         int texturenumsurfaces, endsurface;
10705         texture_t *texture;
10706         const msurface_t *surface;
10707         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10708
10709         // if the model is static it doesn't matter what value we give for
10710         // wantnormals and wanttangents, so this logic uses only rules applicable
10711         // to a model, knowing that they are meaningless otherwise
10712         if (ent == r_refdef.scene.worldentity)
10713                 RSurf_ActiveWorldEntity();
10714         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10715                 RSurf_ActiveModelEntity(ent, false, false, false);
10716         else
10717         {
10718                 switch (vid.renderpath)
10719                 {
10720                 case RENDERPATH_GL20:
10721                 case RENDERPATH_D3D9:
10722                 case RENDERPATH_D3D10:
10723                 case RENDERPATH_D3D11:
10724                 case RENDERPATH_SOFT:
10725                 case RENDERPATH_GLES2:
10726                         RSurf_ActiveModelEntity(ent, true, true, false);
10727                         break;
10728                 case RENDERPATH_GL11:
10729                 case RENDERPATH_GL13:
10730                 case RENDERPATH_GLES1:
10731                         RSurf_ActiveModelEntity(ent, true, false, false);
10732                         break;
10733                 }
10734         }
10735
10736         if (r_transparentdepthmasking.integer)
10737         {
10738                 qboolean setup = false;
10739                 for (i = 0;i < numsurfaces;i = j)
10740                 {
10741                         j = i + 1;
10742                         surface = rsurface.modelsurfaces + surfacelist[i];
10743                         texture = surface->texture;
10744                         rsurface.texture = R_GetCurrentTexture(texture);
10745                         rsurface.lightmaptexture = NULL;
10746                         rsurface.deluxemaptexture = NULL;
10747                         rsurface.uselightmaptexture = false;
10748                         // scan ahead until we find a different texture
10749                         endsurface = min(i + 1024, numsurfaces);
10750                         texturenumsurfaces = 0;
10751                         texturesurfacelist[texturenumsurfaces++] = surface;
10752                         for (;j < endsurface;j++)
10753                         {
10754                                 surface = rsurface.modelsurfaces + surfacelist[j];
10755                                 if (texture != surface->texture)
10756                                         break;
10757                                 texturesurfacelist[texturenumsurfaces++] = surface;
10758                         }
10759                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10760                                 continue;
10761                         // render the range of surfaces as depth
10762                         if (!setup)
10763                         {
10764                                 setup = true;
10765                                 GL_ColorMask(0,0,0,0);
10766                                 GL_Color(1,1,1,1);
10767                                 GL_DepthTest(true);
10768                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10769                                 GL_DepthMask(true);
10770 //                              R_Mesh_ResetTextureState();
10771                         }
10772                         RSurf_SetupDepthAndCulling();
10773                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10774                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10775                         if (rsurface.batchvertex3fbuffer)
10776                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10777                         else
10778                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10779                         RSurf_DrawBatch();
10780                 }
10781                 if (setup)
10782                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10783         }
10784
10785         for (i = 0;i < numsurfaces;i = j)
10786         {
10787                 j = i + 1;
10788                 surface = rsurface.modelsurfaces + surfacelist[i];
10789                 texture = surface->texture;
10790                 rsurface.texture = R_GetCurrentTexture(texture);
10791                 // scan ahead until we find a different texture
10792                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10793                 texturenumsurfaces = 0;
10794                 texturesurfacelist[texturenumsurfaces++] = surface;
10795                 if(FAKELIGHT_ENABLED)
10796                 {
10797                         rsurface.lightmaptexture = NULL;
10798                         rsurface.deluxemaptexture = NULL;
10799                         rsurface.uselightmaptexture = false;
10800                         for (;j < endsurface;j++)
10801                         {
10802                                 surface = rsurface.modelsurfaces + surfacelist[j];
10803                                 if (texture != surface->texture)
10804                                         break;
10805                                 texturesurfacelist[texturenumsurfaces++] = surface;
10806                         }
10807                 }
10808                 else
10809                 {
10810                         rsurface.lightmaptexture = surface->lightmaptexture;
10811                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10812                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10813                         for (;j < endsurface;j++)
10814                         {
10815                                 surface = rsurface.modelsurfaces + surfacelist[j];
10816                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10817                                         break;
10818                                 texturesurfacelist[texturenumsurfaces++] = surface;
10819                         }
10820                 }
10821                 // render the range of surfaces
10822                 if (ent == r_refdef.scene.worldentity)
10823                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10824                 else
10825                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10826         }
10827         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10828 }
10829
10830 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10831 {
10832         // transparent surfaces get pushed off into the transparent queue
10833         int surfacelistindex;
10834         const msurface_t *surface;
10835         vec3_t tempcenter, center;
10836         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10837         {
10838                 surface = texturesurfacelist[surfacelistindex];
10839                 if (r_transparent_sortsurfacesbynearest.integer)
10840                 {
10841                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10842                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10843                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10844                 }
10845                 else
10846                 {
10847                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10848                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10849                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10850                 }
10851                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10852                 if (rsurface.entity->transparent_offset) // transparent offset
10853                 {
10854                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10855                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10856                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10857                 }
10858                 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);
10859         }
10860 }
10861
10862 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10863 {
10864         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10865                 return;
10866         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10867                 return;
10868         RSurf_SetupDepthAndCulling();
10869         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10870         if (rsurface.batchvertex3fbuffer)
10871                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10872         else
10873                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10874         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10875         RSurf_DrawBatch();
10876 }
10877
10878 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10879 {
10880         CHECKGLERROR
10881         if (depthonly)
10882                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10883         else if (prepass)
10884         {
10885                 if (!rsurface.texture->currentnumlayers)
10886                         return;
10887                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10888                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10889                 else
10890                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10891         }
10892         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10893                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10894         else if (!rsurface.texture->currentnumlayers)
10895                 return;
10896         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10897         {
10898                 // in the deferred case, transparent surfaces were queued during prepass
10899                 if (!r_shadow_usingdeferredprepass)
10900                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10901         }
10902         else
10903         {
10904                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10905                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10906         }
10907         CHECKGLERROR
10908 }
10909
10910 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10911 {
10912         int i, j;
10913         texture_t *texture;
10914         R_FrameData_SetMark();
10915         // break the surface list down into batches by texture and use of lightmapping
10916         for (i = 0;i < numsurfaces;i = j)
10917         {
10918                 j = i + 1;
10919                 // texture is the base texture pointer, rsurface.texture is the
10920                 // current frame/skin the texture is directing us to use (for example
10921                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10922                 // use skin 1 instead)
10923                 texture = surfacelist[i]->texture;
10924                 rsurface.texture = R_GetCurrentTexture(texture);
10925                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10926                 {
10927                         // if this texture is not the kind we want, skip ahead to the next one
10928                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10929                                 ;
10930                         continue;
10931                 }
10932                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10933                 {
10934                         rsurface.lightmaptexture = NULL;
10935                         rsurface.deluxemaptexture = NULL;
10936                         rsurface.uselightmaptexture = false;
10937                         // simply scan ahead until we find a different texture or lightmap state
10938                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10939                                 ;
10940                 }
10941                 else
10942                 {
10943                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10944                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10945                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10946                         // simply scan ahead until we find a different texture or lightmap state
10947                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10948                                 ;
10949                 }
10950                 // render the range of surfaces
10951                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10952         }
10953         R_FrameData_ReturnToMark();
10954 }
10955
10956 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10957 {
10958         CHECKGLERROR
10959         if (depthonly)
10960                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10961         else if (prepass)
10962         {
10963                 if (!rsurface.texture->currentnumlayers)
10964                         return;
10965                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10966                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10967                 else
10968                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10969         }
10970         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10971                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10972         else if (!rsurface.texture->currentnumlayers)
10973                 return;
10974         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10975         {
10976                 // in the deferred case, transparent surfaces were queued during prepass
10977                 if (!r_shadow_usingdeferredprepass)
10978                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10979         }
10980         else
10981         {
10982                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10983                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10984         }
10985         CHECKGLERROR
10986 }
10987
10988 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10989 {
10990         int i, j;
10991         texture_t *texture;
10992         R_FrameData_SetMark();
10993         // break the surface list down into batches by texture and use of lightmapping
10994         for (i = 0;i < numsurfaces;i = j)
10995         {
10996                 j = i + 1;
10997                 // texture is the base texture pointer, rsurface.texture is the
10998                 // current frame/skin the texture is directing us to use (for example
10999                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11000                 // use skin 1 instead)
11001                 texture = surfacelist[i]->texture;
11002                 rsurface.texture = R_GetCurrentTexture(texture);
11003                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11004                 {
11005                         // if this texture is not the kind we want, skip ahead to the next one
11006                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11007                                 ;
11008                         continue;
11009                 }
11010                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11011                 {
11012                         rsurface.lightmaptexture = NULL;
11013                         rsurface.deluxemaptexture = NULL;
11014                         rsurface.uselightmaptexture = false;
11015                         // simply scan ahead until we find a different texture or lightmap state
11016                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11017                                 ;
11018                 }
11019                 else
11020                 {
11021                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11022                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11023                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11024                         // simply scan ahead until we find a different texture or lightmap state
11025                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11026                                 ;
11027                 }
11028                 // render the range of surfaces
11029                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11030         }
11031         R_FrameData_ReturnToMark();
11032 }
11033
11034 float locboxvertex3f[6*4*3] =
11035 {
11036         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11037         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11038         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11039         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11040         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11041         1,0,0, 0,0,0, 0,1,0, 1,1,0
11042 };
11043
11044 unsigned short locboxelements[6*2*3] =
11045 {
11046          0, 1, 2, 0, 2, 3,
11047          4, 5, 6, 4, 6, 7,
11048          8, 9,10, 8,10,11,
11049         12,13,14, 12,14,15,
11050         16,17,18, 16,18,19,
11051         20,21,22, 20,22,23
11052 };
11053
11054 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11055 {
11056         int i, j;
11057         cl_locnode_t *loc = (cl_locnode_t *)ent;
11058         vec3_t mins, size;
11059         float vertex3f[6*4*3];
11060         CHECKGLERROR
11061         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11062         GL_DepthMask(false);
11063         GL_DepthRange(0, 1);
11064         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11065         GL_DepthTest(true);
11066         GL_CullFace(GL_NONE);
11067         R_EntityMatrix(&identitymatrix);
11068
11069 //      R_Mesh_ResetTextureState();
11070
11071         i = surfacelist[0];
11072         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11073                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11074                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11075                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11076
11077         if (VectorCompare(loc->mins, loc->maxs))
11078         {
11079                 VectorSet(size, 2, 2, 2);
11080                 VectorMA(loc->mins, -0.5f, size, mins);
11081         }
11082         else
11083         {
11084                 VectorCopy(loc->mins, mins);
11085                 VectorSubtract(loc->maxs, loc->mins, size);
11086         }
11087
11088         for (i = 0;i < 6*4*3;)
11089                 for (j = 0;j < 3;j++, i++)
11090                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11091
11092         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11093         R_SetupShader_Generic_NoTexture(false, false);
11094         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11095 }
11096
11097 void R_DrawLocs(void)
11098 {
11099         int index;
11100         cl_locnode_t *loc, *nearestloc;
11101         vec3_t center;
11102         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11103         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11104         {
11105                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11106                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11107         }
11108 }
11109
11110 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11111 {
11112         if (decalsystem->decals)
11113                 Mem_Free(decalsystem->decals);
11114         memset(decalsystem, 0, sizeof(*decalsystem));
11115 }
11116
11117 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)
11118 {
11119         tridecal_t *decal;
11120         tridecal_t *decals;
11121         int i;
11122
11123         // expand or initialize the system
11124         if (decalsystem->maxdecals <= decalsystem->numdecals)
11125         {
11126                 decalsystem_t old = *decalsystem;
11127                 qboolean useshortelements;
11128                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11129                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11130                 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)));
11131                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11132                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11133                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11134                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11135                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11136                 if (decalsystem->numdecals)
11137                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11138                 if (old.decals)
11139                         Mem_Free(old.decals);
11140                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11141                         decalsystem->element3i[i] = i;
11142                 if (useshortelements)
11143                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11144                                 decalsystem->element3s[i] = i;
11145         }
11146
11147         // grab a decal and search for another free slot for the next one
11148         decals = decalsystem->decals;
11149         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11150         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11151                 ;
11152         decalsystem->freedecal = i;
11153         if (decalsystem->numdecals <= i)
11154                 decalsystem->numdecals = i + 1;
11155
11156         // initialize the decal
11157         decal->lived = 0;
11158         decal->triangleindex = triangleindex;
11159         decal->surfaceindex = surfaceindex;
11160         decal->decalsequence = decalsequence;
11161         decal->color4f[0][0] = c0[0];
11162         decal->color4f[0][1] = c0[1];
11163         decal->color4f[0][2] = c0[2];
11164         decal->color4f[0][3] = 1;
11165         decal->color4f[1][0] = c1[0];
11166         decal->color4f[1][1] = c1[1];
11167         decal->color4f[1][2] = c1[2];
11168         decal->color4f[1][3] = 1;
11169         decal->color4f[2][0] = c2[0];
11170         decal->color4f[2][1] = c2[1];
11171         decal->color4f[2][2] = c2[2];
11172         decal->color4f[2][3] = 1;
11173         decal->vertex3f[0][0] = v0[0];
11174         decal->vertex3f[0][1] = v0[1];
11175         decal->vertex3f[0][2] = v0[2];
11176         decal->vertex3f[1][0] = v1[0];
11177         decal->vertex3f[1][1] = v1[1];
11178         decal->vertex3f[1][2] = v1[2];
11179         decal->vertex3f[2][0] = v2[0];
11180         decal->vertex3f[2][1] = v2[1];
11181         decal->vertex3f[2][2] = v2[2];
11182         decal->texcoord2f[0][0] = t0[0];
11183         decal->texcoord2f[0][1] = t0[1];
11184         decal->texcoord2f[1][0] = t1[0];
11185         decal->texcoord2f[1][1] = t1[1];
11186         decal->texcoord2f[2][0] = t2[0];
11187         decal->texcoord2f[2][1] = t2[1];
11188         TriangleNormal(v0, v1, v2, decal->plane);
11189         VectorNormalize(decal->plane);
11190         decal->plane[3] = DotProduct(v0, decal->plane);
11191 }
11192
11193 extern cvar_t cl_decals_bias;
11194 extern cvar_t cl_decals_models;
11195 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11196 // baseparms, parms, temps
11197 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)
11198 {
11199         int cornerindex;
11200         int index;
11201         float v[9][3];
11202         const float *vertex3f;
11203         const float *normal3f;
11204         int numpoints;
11205         float points[2][9][3];
11206         float temp[3];
11207         float tc[9][2];
11208         float f;
11209         float c[9][4];
11210         const int *e;
11211
11212         e = rsurface.modelelement3i + 3*triangleindex;
11213
11214         vertex3f = rsurface.modelvertex3f;
11215         normal3f = rsurface.modelnormal3f;
11216
11217         if (normal3f)
11218         {
11219                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11220                 {
11221                         index = 3*e[cornerindex];
11222                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11223                 }
11224         }
11225         else
11226         {
11227                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11228                 {
11229                         index = 3*e[cornerindex];
11230                         VectorCopy(vertex3f + index, v[cornerindex]);
11231                 }
11232         }
11233
11234         // cull backfaces
11235         //TriangleNormal(v[0], v[1], v[2], normal);
11236         //if (DotProduct(normal, localnormal) < 0.0f)
11237         //      continue;
11238         // clip by each of the box planes formed from the projection matrix
11239         // if anything survives, we emit the decal
11240         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]);
11241         if (numpoints < 3)
11242                 return;
11243         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]);
11244         if (numpoints < 3)
11245                 return;
11246         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]);
11247         if (numpoints < 3)
11248                 return;
11249         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]);
11250         if (numpoints < 3)
11251                 return;
11252         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]);
11253         if (numpoints < 3)
11254                 return;
11255         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]);
11256         if (numpoints < 3)
11257                 return;
11258         // some part of the triangle survived, so we have to accept it...
11259         if (dynamic)
11260         {
11261                 // dynamic always uses the original triangle
11262                 numpoints = 3;
11263                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11264                 {
11265                         index = 3*e[cornerindex];
11266                         VectorCopy(vertex3f + index, v[cornerindex]);
11267                 }
11268         }
11269         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11270         {
11271                 // convert vertex positions to texcoords
11272                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11273                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11274                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11275                 // calculate distance fade from the projection origin
11276                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11277                 f = bound(0.0f, f, 1.0f);
11278                 c[cornerindex][0] = r * f;
11279                 c[cornerindex][1] = g * f;
11280                 c[cornerindex][2] = b * f;
11281                 c[cornerindex][3] = 1.0f;
11282                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11283         }
11284         if (dynamic)
11285                 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);
11286         else
11287                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11288                         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);
11289 }
11290 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)
11291 {
11292         matrix4x4_t projection;
11293         decalsystem_t *decalsystem;
11294         qboolean dynamic;
11295         dp_model_t *model;
11296         const msurface_t *surface;
11297         const msurface_t *surfaces;
11298         const int *surfacelist;
11299         const texture_t *texture;
11300         int numtriangles;
11301         int numsurfacelist;
11302         int surfacelistindex;
11303         int surfaceindex;
11304         int triangleindex;
11305         float localorigin[3];
11306         float localnormal[3];
11307         float localmins[3];
11308         float localmaxs[3];
11309         float localsize;
11310         //float normal[3];
11311         float planes[6][4];
11312         float angles[3];
11313         bih_t *bih;
11314         int bih_triangles_count;
11315         int bih_triangles[256];
11316         int bih_surfaces[256];
11317
11318         decalsystem = &ent->decalsystem;
11319         model = ent->model;
11320         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11321         {
11322                 R_DecalSystem_Reset(&ent->decalsystem);
11323                 return;
11324         }
11325
11326         if (!model->brush.data_leafs && !cl_decals_models.integer)
11327         {
11328                 if (decalsystem->model)
11329                         R_DecalSystem_Reset(decalsystem);
11330                 return;
11331         }
11332
11333         if (decalsystem->model != model)
11334                 R_DecalSystem_Reset(decalsystem);
11335         decalsystem->model = model;
11336
11337         RSurf_ActiveModelEntity(ent, true, false, false);
11338
11339         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11340         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11341         VectorNormalize(localnormal);
11342         localsize = worldsize*rsurface.inversematrixscale;
11343         localmins[0] = localorigin[0] - localsize;
11344         localmins[1] = localorigin[1] - localsize;
11345         localmins[2] = localorigin[2] - localsize;
11346         localmaxs[0] = localorigin[0] + localsize;
11347         localmaxs[1] = localorigin[1] + localsize;
11348         localmaxs[2] = localorigin[2] + localsize;
11349
11350         //VectorCopy(localnormal, planes[4]);
11351         //VectorVectors(planes[4], planes[2], planes[0]);
11352         AnglesFromVectors(angles, localnormal, NULL, false);
11353         AngleVectors(angles, planes[0], planes[2], planes[4]);
11354         VectorNegate(planes[0], planes[1]);
11355         VectorNegate(planes[2], planes[3]);
11356         VectorNegate(planes[4], planes[5]);
11357         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11358         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11359         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11360         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11361         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11362         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11363
11364 #if 1
11365 // works
11366 {
11367         matrix4x4_t forwardprojection;
11368         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11369         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11370 }
11371 #else
11372 // broken
11373 {
11374         float projectionvector[4][3];
11375         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11376         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11377         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11378         projectionvector[0][0] = planes[0][0] * ilocalsize;
11379         projectionvector[0][1] = planes[1][0] * ilocalsize;
11380         projectionvector[0][2] = planes[2][0] * ilocalsize;
11381         projectionvector[1][0] = planes[0][1] * ilocalsize;
11382         projectionvector[1][1] = planes[1][1] * ilocalsize;
11383         projectionvector[1][2] = planes[2][1] * ilocalsize;
11384         projectionvector[2][0] = planes[0][2] * ilocalsize;
11385         projectionvector[2][1] = planes[1][2] * ilocalsize;
11386         projectionvector[2][2] = planes[2][2] * ilocalsize;
11387         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11388         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11389         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11390         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11391 }
11392 #endif
11393
11394         dynamic = model->surfmesh.isanimated;
11395         numsurfacelist = model->nummodelsurfaces;
11396         surfacelist = model->sortedmodelsurfaces;
11397         surfaces = model->data_surfaces;
11398
11399         bih = NULL;
11400         bih_triangles_count = -1;
11401         if(!dynamic)
11402         {
11403                 if(model->render_bih.numleafs)
11404                         bih = &model->render_bih;
11405                 else if(model->collision_bih.numleafs)
11406                         bih = &model->collision_bih;
11407         }
11408         if(bih)
11409                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11410         if(bih_triangles_count == 0)
11411                 return;
11412         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11413                 return;
11414         if(bih_triangles_count > 0)
11415         {
11416                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11417                 {
11418                         surfaceindex = bih_surfaces[triangleindex];
11419                         surface = surfaces + surfaceindex;
11420                         texture = surface->texture;
11421                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11422                                 continue;
11423                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11424                                 continue;
11425                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11426                 }
11427         }
11428         else
11429         {
11430                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11431                 {
11432                         surfaceindex = surfacelist[surfacelistindex];
11433                         surface = surfaces + surfaceindex;
11434                         // check cull box first because it rejects more than any other check
11435                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11436                                 continue;
11437                         // skip transparent surfaces
11438                         texture = surface->texture;
11439                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11440                                 continue;
11441                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11442                                 continue;
11443                         numtriangles = surface->num_triangles;
11444                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11445                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11446                 }
11447         }
11448 }
11449
11450 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11451 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)
11452 {
11453         int renderentityindex;
11454         float worldmins[3];
11455         float worldmaxs[3];
11456         entity_render_t *ent;
11457
11458         if (!cl_decals_newsystem.integer)
11459                 return;
11460
11461         worldmins[0] = worldorigin[0] - worldsize;
11462         worldmins[1] = worldorigin[1] - worldsize;
11463         worldmins[2] = worldorigin[2] - worldsize;
11464         worldmaxs[0] = worldorigin[0] + worldsize;
11465         worldmaxs[1] = worldorigin[1] + worldsize;
11466         worldmaxs[2] = worldorigin[2] + worldsize;
11467
11468         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11469
11470         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11471         {
11472                 ent = r_refdef.scene.entities[renderentityindex];
11473                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11474                         continue;
11475
11476                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11477         }
11478 }
11479
11480 typedef struct r_decalsystem_splatqueue_s
11481 {
11482         vec3_t worldorigin;
11483         vec3_t worldnormal;
11484         float color[4];
11485         float tcrange[4];
11486         float worldsize;
11487         int decalsequence;
11488 }
11489 r_decalsystem_splatqueue_t;
11490
11491 int r_decalsystem_numqueued = 0;
11492 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11493
11494 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)
11495 {
11496         r_decalsystem_splatqueue_t *queue;
11497
11498         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11499                 return;
11500
11501         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11502         VectorCopy(worldorigin, queue->worldorigin);
11503         VectorCopy(worldnormal, queue->worldnormal);
11504         Vector4Set(queue->color, r, g, b, a);
11505         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11506         queue->worldsize = worldsize;
11507         queue->decalsequence = cl.decalsequence++;
11508 }
11509
11510 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11511 {
11512         int i;
11513         r_decalsystem_splatqueue_t *queue;
11514
11515         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11516                 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);
11517         r_decalsystem_numqueued = 0;
11518 }
11519
11520 extern cvar_t cl_decals_max;
11521 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11522 {
11523         int i;
11524         decalsystem_t *decalsystem = &ent->decalsystem;
11525         int numdecals;
11526         int killsequence;
11527         tridecal_t *decal;
11528         float frametime;
11529         float lifetime;
11530
11531         if (!decalsystem->numdecals)
11532                 return;
11533
11534         if (r_showsurfaces.integer)
11535                 return;
11536
11537         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11538         {
11539                 R_DecalSystem_Reset(decalsystem);
11540                 return;
11541         }
11542
11543         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11544         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11545
11546         if (decalsystem->lastupdatetime)
11547                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11548         else
11549                 frametime = 0;
11550         decalsystem->lastupdatetime = r_refdef.scene.time;
11551         numdecals = decalsystem->numdecals;
11552
11553         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11554         {
11555                 if (decal->color4f[0][3])
11556                 {
11557                         decal->lived += frametime;
11558                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11559                         {
11560                                 memset(decal, 0, sizeof(*decal));
11561                                 if (decalsystem->freedecal > i)
11562                                         decalsystem->freedecal = i;
11563                         }
11564                 }
11565         }
11566         decal = decalsystem->decals;
11567         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11568                 numdecals--;
11569
11570         // collapse the array by shuffling the tail decals into the gaps
11571         for (;;)
11572         {
11573                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11574                         decalsystem->freedecal++;
11575                 if (decalsystem->freedecal == numdecals)
11576                         break;
11577                 decal[decalsystem->freedecal] = decal[--numdecals];
11578         }
11579
11580         decalsystem->numdecals = numdecals;
11581
11582         if (numdecals <= 0)
11583         {
11584                 // if there are no decals left, reset decalsystem
11585                 R_DecalSystem_Reset(decalsystem);
11586         }
11587 }
11588
11589 extern skinframe_t *decalskinframe;
11590 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11591 {
11592         int i;
11593         decalsystem_t *decalsystem = &ent->decalsystem;
11594         int numdecals;
11595         tridecal_t *decal;
11596         float faderate;
11597         float alpha;
11598         float *v3f;
11599         float *c4f;
11600         float *t2f;
11601         const int *e;
11602         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11603         int numtris = 0;
11604
11605         numdecals = decalsystem->numdecals;
11606         if (!numdecals)
11607                 return;
11608
11609         if (r_showsurfaces.integer)
11610                 return;
11611
11612         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11613         {
11614                 R_DecalSystem_Reset(decalsystem);
11615                 return;
11616         }
11617
11618         // if the model is static it doesn't matter what value we give for
11619         // wantnormals and wanttangents, so this logic uses only rules applicable
11620         // to a model, knowing that they are meaningless otherwise
11621         if (ent == r_refdef.scene.worldentity)
11622                 RSurf_ActiveWorldEntity();
11623         else
11624                 RSurf_ActiveModelEntity(ent, false, false, false);
11625
11626         decalsystem->lastupdatetime = r_refdef.scene.time;
11627
11628         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11629
11630         // update vertex positions for animated models
11631         v3f = decalsystem->vertex3f;
11632         c4f = decalsystem->color4f;
11633         t2f = decalsystem->texcoord2f;
11634         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11635         {
11636                 if (!decal->color4f[0][3])
11637                         continue;
11638
11639                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11640                         continue;
11641
11642                 // skip backfaces
11643                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11644                         continue;
11645
11646                 // update color values for fading decals
11647                 if (decal->lived >= cl_decals_time.value)
11648                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11649                 else
11650                         alpha = 1.0f;
11651
11652                 c4f[ 0] = decal->color4f[0][0] * alpha;
11653                 c4f[ 1] = decal->color4f[0][1] * alpha;
11654                 c4f[ 2] = decal->color4f[0][2] * alpha;
11655                 c4f[ 3] = 1;
11656                 c4f[ 4] = decal->color4f[1][0] * alpha;
11657                 c4f[ 5] = decal->color4f[1][1] * alpha;
11658                 c4f[ 6] = decal->color4f[1][2] * alpha;
11659                 c4f[ 7] = 1;
11660                 c4f[ 8] = decal->color4f[2][0] * alpha;
11661                 c4f[ 9] = decal->color4f[2][1] * alpha;
11662                 c4f[10] = decal->color4f[2][2] * alpha;
11663                 c4f[11] = 1;
11664
11665                 t2f[0] = decal->texcoord2f[0][0];
11666                 t2f[1] = decal->texcoord2f[0][1];
11667                 t2f[2] = decal->texcoord2f[1][0];
11668                 t2f[3] = decal->texcoord2f[1][1];
11669                 t2f[4] = decal->texcoord2f[2][0];
11670                 t2f[5] = decal->texcoord2f[2][1];
11671
11672                 // update vertex positions for animated models
11673                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11674                 {
11675                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11676                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11677                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11678                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11679                 }
11680                 else
11681                 {
11682                         VectorCopy(decal->vertex3f[0], v3f);
11683                         VectorCopy(decal->vertex3f[1], v3f + 3);
11684                         VectorCopy(decal->vertex3f[2], v3f + 6);
11685                 }
11686
11687                 if (r_refdef.fogenabled)
11688                 {
11689                         alpha = RSurf_FogVertex(v3f);
11690                         VectorScale(c4f, alpha, c4f);
11691                         alpha = RSurf_FogVertex(v3f + 3);
11692                         VectorScale(c4f + 4, alpha, c4f + 4);
11693                         alpha = RSurf_FogVertex(v3f + 6);
11694                         VectorScale(c4f + 8, alpha, c4f + 8);
11695                 }
11696
11697                 v3f += 9;
11698                 c4f += 12;
11699                 t2f += 6;
11700                 numtris++;
11701         }
11702
11703         if (numtris > 0)
11704         {
11705                 r_refdef.stats.drawndecals += numtris;
11706
11707                 // now render the decals all at once
11708                 // (this assumes they all use one particle font texture!)
11709                 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);
11710 //              R_Mesh_ResetTextureState();
11711                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11712                 GL_DepthMask(false);
11713                 GL_DepthRange(0, 1);
11714                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11715                 GL_DepthTest(true);
11716                 GL_CullFace(GL_NONE);
11717                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11718                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11719                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11720         }
11721 }
11722
11723 static void R_DrawModelDecals(void)
11724 {
11725         int i, numdecals;
11726
11727         // fade faster when there are too many decals
11728         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11729         for (i = 0;i < r_refdef.scene.numentities;i++)
11730                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11731
11732         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11733         for (i = 0;i < r_refdef.scene.numentities;i++)
11734                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11735                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11736
11737         R_DecalSystem_ApplySplatEntitiesQueue();
11738
11739         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11740         for (i = 0;i < r_refdef.scene.numentities;i++)
11741                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11742
11743         r_refdef.stats.totaldecals += numdecals;
11744
11745         if (r_showsurfaces.integer)
11746                 return;
11747
11748         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11749
11750         for (i = 0;i < r_refdef.scene.numentities;i++)
11751         {
11752                 if (!r_refdef.viewcache.entityvisible[i])
11753                         continue;
11754                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11755                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11756         }
11757 }
11758
11759 extern cvar_t mod_collision_bih;
11760 static void R_DrawDebugModel(void)
11761 {
11762         entity_render_t *ent = rsurface.entity;
11763         int i, j, k, l, flagsmask;
11764         const msurface_t *surface;
11765         dp_model_t *model = ent->model;
11766         vec3_t v;
11767
11768         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11769                 return;
11770
11771         if (r_showoverdraw.value > 0)
11772         {
11773                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11774                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11775                 R_SetupShader_Generic_NoTexture(false, false);
11776                 GL_DepthTest(false);
11777                 GL_DepthMask(false);
11778                 GL_DepthRange(0, 1);
11779                 GL_BlendFunc(GL_ONE, GL_ONE);
11780                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11781                 {
11782                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11783                                 continue;
11784                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11785                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11786                         {
11787                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11788                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11789                                 if (!rsurface.texture->currentlayers->depthmask)
11790                                         GL_Color(c, 0, 0, 1.0f);
11791                                 else if (ent == r_refdef.scene.worldentity)
11792                                         GL_Color(c, c, c, 1.0f);
11793                                 else
11794                                         GL_Color(0, c, 0, 1.0f);
11795                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11796                                 RSurf_DrawBatch();
11797                         }
11798                 }
11799                 rsurface.texture = NULL;
11800         }
11801
11802         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11803
11804 //      R_Mesh_ResetTextureState();
11805         R_SetupShader_Generic_NoTexture(false, false);
11806         GL_DepthRange(0, 1);
11807         GL_DepthTest(!r_showdisabledepthtest.integer);
11808         GL_DepthMask(false);
11809         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11810
11811         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11812         {
11813                 int triangleindex;
11814                 int bihleafindex;
11815                 qboolean cullbox = false;
11816                 const q3mbrush_t *brush;
11817                 const bih_t *bih = &model->collision_bih;
11818                 const bih_leaf_t *bihleaf;
11819                 float vertex3f[3][3];
11820                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11821                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11822                 {
11823                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11824                                 continue;
11825                         switch (bihleaf->type)
11826                         {
11827                         case BIH_BRUSH:
11828                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11829                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11830                                 {
11831                                         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);
11832                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11833                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11834                                 }
11835                                 break;
11836                         case BIH_COLLISIONTRIANGLE:
11837                                 triangleindex = bihleaf->itemindex;
11838                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11839                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11840                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11841                                 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);
11842                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11843                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11844                                 break;
11845                         case BIH_RENDERTRIANGLE:
11846                                 triangleindex = bihleaf->itemindex;
11847                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11848                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11849                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11850                                 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);
11851                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11852                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11853                                 break;
11854                         }
11855                 }
11856         }
11857
11858         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11859
11860 #ifndef USE_GLES2
11861         if (r_showtris.integer && qglPolygonMode)
11862         {
11863                 if (r_showdisabledepthtest.integer)
11864                 {
11865                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11866                         GL_DepthMask(false);
11867                 }
11868                 else
11869                 {
11870                         GL_BlendFunc(GL_ONE, GL_ZERO);
11871                         GL_DepthMask(true);
11872                 }
11873                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11874                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11875                 {
11876                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11877                                 continue;
11878                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11879                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11880                         {
11881                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11882                                 if (!rsurface.texture->currentlayers->depthmask)
11883                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11884                                 else if (ent == r_refdef.scene.worldentity)
11885                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11886                                 else
11887                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11888                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11889                                 RSurf_DrawBatch();
11890                         }
11891                 }
11892                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11893                 rsurface.texture = NULL;
11894         }
11895
11896         if (r_shownormals.value != 0 && qglBegin)
11897         {
11898                 if (r_showdisabledepthtest.integer)
11899                 {
11900                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11901                         GL_DepthMask(false);
11902                 }
11903                 else
11904                 {
11905                         GL_BlendFunc(GL_ONE, GL_ZERO);
11906                         GL_DepthMask(true);
11907                 }
11908                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11909                 {
11910                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11911                                 continue;
11912                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11913                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11914                         {
11915                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11916                                 qglBegin(GL_LINES);
11917                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11918                                 {
11919                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11920                                         {
11921                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11922                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11923                                                 qglVertex3f(v[0], v[1], v[2]);
11924                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11925                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11926                                                 qglVertex3f(v[0], v[1], v[2]);
11927                                         }
11928                                 }
11929                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11930                                 {
11931                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11932                                         {
11933                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11934                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11935                                                 qglVertex3f(v[0], v[1], v[2]);
11936                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11937                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11938                                                 qglVertex3f(v[0], v[1], v[2]);
11939                                         }
11940                                 }
11941                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11942                                 {
11943                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11944                                         {
11945                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11946                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11947                                                 qglVertex3f(v[0], v[1], v[2]);
11948                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11949                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11950                                                 qglVertex3f(v[0], v[1], v[2]);
11951                                         }
11952                                 }
11953                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11954                                 {
11955                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11956                                         {
11957                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11958                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11959                                                 qglVertex3f(v[0], v[1], v[2]);
11960                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11961                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11962                                                 qglVertex3f(v[0], v[1], v[2]);
11963                                         }
11964                                 }
11965                                 qglEnd();
11966                                 CHECKGLERROR
11967                         }
11968                 }
11969                 rsurface.texture = NULL;
11970         }
11971 #endif
11972 }
11973
11974 int r_maxsurfacelist = 0;
11975 const msurface_t **r_surfacelist = NULL;
11976 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11977 {
11978         int i, j, endj, flagsmask;
11979         dp_model_t *model = r_refdef.scene.worldmodel;
11980         msurface_t *surfaces;
11981         unsigned char *update;
11982         int numsurfacelist = 0;
11983         if (model == NULL)
11984                 return;
11985
11986         if (r_maxsurfacelist < model->num_surfaces)
11987         {
11988                 r_maxsurfacelist = model->num_surfaces;
11989                 if (r_surfacelist)
11990                         Mem_Free((msurface_t**)r_surfacelist);
11991                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11992         }
11993
11994         RSurf_ActiveWorldEntity();
11995
11996         surfaces = model->data_surfaces;
11997         update = model->brushq1.lightmapupdateflags;
11998
11999         // update light styles on this submodel
12000         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12001         {
12002                 model_brush_lightstyleinfo_t *style;
12003                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12004                 {
12005                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12006                         {
12007                                 int *list = style->surfacelist;
12008                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12009                                 for (j = 0;j < style->numsurfaces;j++)
12010                                         update[list[j]] = true;
12011                         }
12012                 }
12013         }
12014
12015         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12016
12017         if (debug)
12018         {
12019                 R_DrawDebugModel();
12020                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12021                 return;
12022         }
12023
12024         rsurface.lightmaptexture = NULL;
12025         rsurface.deluxemaptexture = NULL;
12026         rsurface.uselightmaptexture = false;
12027         rsurface.texture = NULL;
12028         rsurface.rtlight = NULL;
12029         numsurfacelist = 0;
12030         // add visible surfaces to draw list
12031         for (i = 0;i < model->nummodelsurfaces;i++)
12032         {
12033                 j = model->sortedmodelsurfaces[i];
12034                 if (r_refdef.viewcache.world_surfacevisible[j])
12035                         r_surfacelist[numsurfacelist++] = surfaces + j;
12036         }
12037         // update lightmaps if needed
12038         if (model->brushq1.firstrender)
12039         {
12040                 model->brushq1.firstrender = false;
12041                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12042                         if (update[j])
12043                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12044         }
12045         else if (update)
12046         {
12047                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12048                         if (r_refdef.viewcache.world_surfacevisible[j])
12049                                 if (update[j])
12050                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12051         }
12052         // don't do anything if there were no surfaces
12053         if (!numsurfacelist)
12054         {
12055                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12056                 return;
12057         }
12058         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12059
12060         // add to stats if desired
12061         if (r_speeds.integer && !skysurfaces && !depthonly)
12062         {
12063                 r_refdef.stats.world_surfaces += numsurfacelist;
12064                 for (j = 0;j < numsurfacelist;j++)
12065                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12066         }
12067
12068         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12069 }
12070
12071 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12072 {
12073         int i, j, endj, flagsmask;
12074         dp_model_t *model = ent->model;
12075         msurface_t *surfaces;
12076         unsigned char *update;
12077         int numsurfacelist = 0;
12078         if (model == NULL)
12079                 return;
12080
12081         if (r_maxsurfacelist < model->num_surfaces)
12082         {
12083                 r_maxsurfacelist = model->num_surfaces;
12084                 if (r_surfacelist)
12085                         Mem_Free((msurface_t **)r_surfacelist);
12086                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12087         }
12088
12089         // if the model is static it doesn't matter what value we give for
12090         // wantnormals and wanttangents, so this logic uses only rules applicable
12091         // to a model, knowing that they are meaningless otherwise
12092         if (ent == r_refdef.scene.worldentity)
12093                 RSurf_ActiveWorldEntity();
12094         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12095                 RSurf_ActiveModelEntity(ent, false, false, false);
12096         else if (prepass)
12097                 RSurf_ActiveModelEntity(ent, true, true, true);
12098         else if (depthonly)
12099         {
12100                 switch (vid.renderpath)
12101                 {
12102                 case RENDERPATH_GL20:
12103                 case RENDERPATH_D3D9:
12104                 case RENDERPATH_D3D10:
12105                 case RENDERPATH_D3D11:
12106                 case RENDERPATH_SOFT:
12107                 case RENDERPATH_GLES2:
12108                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12109                         break;
12110                 case RENDERPATH_GL11:
12111                 case RENDERPATH_GL13:
12112                 case RENDERPATH_GLES1:
12113                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12114                         break;
12115                 }
12116         }
12117         else
12118         {
12119                 switch (vid.renderpath)
12120                 {
12121                 case RENDERPATH_GL20:
12122                 case RENDERPATH_D3D9:
12123                 case RENDERPATH_D3D10:
12124                 case RENDERPATH_D3D11:
12125                 case RENDERPATH_SOFT:
12126                 case RENDERPATH_GLES2:
12127                         RSurf_ActiveModelEntity(ent, true, true, false);
12128                         break;
12129                 case RENDERPATH_GL11:
12130                 case RENDERPATH_GL13:
12131                 case RENDERPATH_GLES1:
12132                         RSurf_ActiveModelEntity(ent, true, false, false);
12133                         break;
12134                 }
12135         }
12136
12137         surfaces = model->data_surfaces;
12138         update = model->brushq1.lightmapupdateflags;
12139
12140         // update light styles
12141         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12142         {
12143                 model_brush_lightstyleinfo_t *style;
12144                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12145                 {
12146                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12147                         {
12148                                 int *list = style->surfacelist;
12149                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12150                                 for (j = 0;j < style->numsurfaces;j++)
12151                                         update[list[j]] = true;
12152                         }
12153                 }
12154         }
12155
12156         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12157
12158         if (debug)
12159         {
12160                 R_DrawDebugModel();
12161                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12162                 return;
12163         }
12164
12165         rsurface.lightmaptexture = NULL;
12166         rsurface.deluxemaptexture = NULL;
12167         rsurface.uselightmaptexture = false;
12168         rsurface.texture = NULL;
12169         rsurface.rtlight = NULL;
12170         numsurfacelist = 0;
12171         // add visible surfaces to draw list
12172         for (i = 0;i < model->nummodelsurfaces;i++)
12173                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12174         // don't do anything if there were no surfaces
12175         if (!numsurfacelist)
12176         {
12177                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12178                 return;
12179         }
12180         // update lightmaps if needed
12181         if (update)
12182         {
12183                 int updated = 0;
12184                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12185                 {
12186                         if (update[j])
12187                         {
12188                                 updated++;
12189                                 R_BuildLightMap(ent, surfaces + j);
12190                         }
12191                 }
12192         }
12193
12194         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12195
12196         // add to stats if desired
12197         if (r_speeds.integer && !skysurfaces && !depthonly)
12198         {
12199                 r_refdef.stats.entities_surfaces += numsurfacelist;
12200                 for (j = 0;j < numsurfacelist;j++)
12201                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12202         }
12203
12204         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12205 }
12206
12207 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12208 {
12209         static texture_t texture;
12210         static msurface_t surface;
12211         const msurface_t *surfacelist = &surface;
12212
12213         // fake enough texture and surface state to render this geometry
12214
12215         texture.update_lastrenderframe = -1; // regenerate this texture
12216         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12217         texture.currentskinframe = skinframe;
12218         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12219         texture.offsetmapping = OFFSETMAPPING_OFF;
12220         texture.offsetscale = 1;
12221         texture.specularscalemod = 1;
12222         texture.specularpowermod = 1;
12223         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12224         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12225         // JUST GREP FOR "specularscalemod = 1".
12226
12227         surface.texture = &texture;
12228         surface.num_triangles = numtriangles;
12229         surface.num_firsttriangle = firsttriangle;
12230         surface.num_vertices = numvertices;
12231         surface.num_firstvertex = firstvertex;
12232
12233         // now render it
12234         rsurface.texture = R_GetCurrentTexture(surface.texture);
12235         rsurface.lightmaptexture = NULL;
12236         rsurface.deluxemaptexture = NULL;
12237         rsurface.uselightmaptexture = false;
12238         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12239 }
12240
12241 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)
12242 {
12243         static msurface_t surface;
12244         const msurface_t *surfacelist = &surface;
12245
12246         // fake enough texture and surface state to render this geometry
12247         surface.texture = texture;
12248         surface.num_triangles = numtriangles;
12249         surface.num_firsttriangle = firsttriangle;
12250         surface.num_vertices = numvertices;
12251         surface.num_firstvertex = firstvertex;
12252
12253         // now render it
12254         rsurface.texture = R_GetCurrentTexture(surface.texture);
12255         rsurface.lightmaptexture = NULL;
12256         rsurface.deluxemaptexture = NULL;
12257         rsurface.uselightmaptexture = false;
12258         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12259 }