]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
increase MAX_CHANNELS to support quakemash
[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 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 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!"};
66 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!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 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)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 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"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 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"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
81 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)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
83
84 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"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 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)"};
97 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
98 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
99 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"};
100 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"};
101 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
102 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"};
103 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"};
104 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"};
105 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
106 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
107 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
108 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
109 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
110 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
111 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
112 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)"};
113 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)"};
114 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
115 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
119
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
123
124 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
125 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
126 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
127 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."};
128 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
129 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
130 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
131 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."};
132 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
133 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
134 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
135 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."};
136 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
137 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"};
138 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"};
139 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
140 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
141 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
142 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
143 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
144 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"};
145 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
146 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
147 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
148 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
149 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
150
151 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
152 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
153 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
154 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
155 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
156 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
157 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
158 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
159
160 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)"};
161 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"};
162
163 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
164 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
165 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
166
167 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"};
168 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"};
169 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"};
170 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
171 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
172 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"};
173 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)"};
174 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)"};
175 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
176
177 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
178 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)"};
179 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
180 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)"};
181 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
182 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)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
185 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"};
186 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."};
187 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196
197 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)"};
198 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
199 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
200 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"};
201 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
202 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
203 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
204 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"};
205 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"};
206 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)"};
207
208 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
209 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
210 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
211 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
212
213 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
214 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
215
216 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
217 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
218 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
219 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
220 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
221 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
222
223 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
224 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
225 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
226 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
227 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
228 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
229 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
230 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
231 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
232 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
233
234 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"};
235
236 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"};
237
238 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
239
240 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
241
242 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)"};
243 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)"};
244 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
245 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
246
247 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
248 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"};
249
250 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."};
251
252 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)"};
253 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
254 {
255         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
256         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
257         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
258         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
259 };
260
261 extern cvar_t v_glslgamma;
262 extern cvar_t v_glslgamma_2d;
263
264 extern qboolean v_flipped_state;
265
266 r_framebufferstate_t r_fb;
267
268 /// shadow volume bsp struct with automatically growing nodes buffer
269 svbsp_t r_svbsp;
270
271 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
272
273 rtexture_t *r_texture_blanknormalmap;
274 rtexture_t *r_texture_white;
275 rtexture_t *r_texture_grey128;
276 rtexture_t *r_texture_black;
277 rtexture_t *r_texture_notexture;
278 rtexture_t *r_texture_whitecube;
279 rtexture_t *r_texture_normalizationcube;
280 rtexture_t *r_texture_fogattenuation;
281 rtexture_t *r_texture_fogheighttexture;
282 rtexture_t *r_texture_gammaramps;
283 unsigned int r_texture_gammaramps_serial;
284 //rtexture_t *r_texture_fogintensity;
285 rtexture_t *r_texture_reflectcube;
286
287 // TODO: hash lookups?
288 typedef struct cubemapinfo_s
289 {
290         char basename[64];
291         rtexture_t *texture;
292 }
293 cubemapinfo_t;
294
295 int r_texture_numcubemaps;
296 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
297
298 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
299 unsigned int r_numqueries;
300 unsigned int r_maxqueries;
301
302 typedef struct r_qwskincache_s
303 {
304         char name[MAX_QPATH];
305         skinframe_t *skinframe;
306 }
307 r_qwskincache_t;
308
309 static r_qwskincache_t *r_qwskincache;
310 static int r_qwskincache_size;
311
312 /// vertex coordinates for a quad that covers the screen exactly
313 extern const float r_screenvertex3f[12];
314 extern const float r_d3dscreenvertex3f[12];
315 const float r_screenvertex3f[12] =
316 {
317         0, 0, 0,
318         1, 0, 0,
319         1, 1, 0,
320         0, 1, 0
321 };
322 const float r_d3dscreenvertex3f[12] =
323 {
324         0, 1, 0,
325         1, 1, 0,
326         1, 0, 0,
327         0, 0, 0
328 };
329
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
331 {
332         int i;
333         for (i = 0;i < verts;i++)
334         {
335                 out[0] = in[0] * r;
336                 out[1] = in[1] * g;
337                 out[2] = in[2] * b;
338                 out[3] = in[3];
339                 in += 4;
340                 out += 4;
341         }
342 }
343
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
345 {
346         int i;
347         for (i = 0;i < verts;i++)
348         {
349                 out[0] = r;
350                 out[1] = g;
351                 out[2] = b;
352                 out[3] = a;
353                 out += 4;
354         }
355 }
356
357 // FIXME: move this to client?
358 void FOG_clear(void)
359 {
360         if (gamemode == GAME_NEHAHRA)
361         {
362                 Cvar_Set("gl_fogenable", "0");
363                 Cvar_Set("gl_fogdensity", "0.2");
364                 Cvar_Set("gl_fogred", "0.3");
365                 Cvar_Set("gl_foggreen", "0.3");
366                 Cvar_Set("gl_fogblue", "0.3");
367         }
368         r_refdef.fog_density = 0;
369         r_refdef.fog_red = 0;
370         r_refdef.fog_green = 0;
371         r_refdef.fog_blue = 0;
372         r_refdef.fog_alpha = 1;
373         r_refdef.fog_start = 0;
374         r_refdef.fog_end = 16384;
375         r_refdef.fog_height = 1<<30;
376         r_refdef.fog_fadedepth = 128;
377         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
378 }
379
380 static void R_BuildBlankTextures(void)
381 {
382         unsigned char data[4];
383         data[2] = 128; // normal X
384         data[1] = 128; // normal Y
385         data[0] = 255; // normal Z
386         data[3] = 255; // height
387         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 255;
389         data[1] = 255;
390         data[2] = 255;
391         data[3] = 255;
392         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393         data[0] = 128;
394         data[1] = 128;
395         data[2] = 128;
396         data[3] = 255;
397         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 0;
399         data[1] = 0;
400         data[2] = 0;
401         data[3] = 255;
402         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNoTexture(void)
406 {
407         int x, y;
408         unsigned char pix[16][16][4];
409         // this makes a light grey/dark grey checkerboard texture
410         for (y = 0;y < 16;y++)
411         {
412                 for (x = 0;x < 16;x++)
413                 {
414                         if ((y < 8) ^ (x < 8))
415                         {
416                                 pix[y][x][0] = 128;
417                                 pix[y][x][1] = 128;
418                                 pix[y][x][2] = 128;
419                                 pix[y][x][3] = 255;
420                         }
421                         else
422                         {
423                                 pix[y][x][0] = 64;
424                                 pix[y][x][1] = 64;
425                                 pix[y][x][2] = 64;
426                                 pix[y][x][3] = 255;
427                         }
428                 }
429         }
430         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildWhiteCube(void)
434 {
435         unsigned char data[6*1*1*4];
436         memset(data, 255, sizeof(data));
437         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
438 }
439
440 static void R_BuildNormalizationCube(void)
441 {
442         int x, y, side;
443         vec3_t v;
444         vec_t s, t, intensity;
445 #define NORMSIZE 64
446         unsigned char *data;
447         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448         for (side = 0;side < 6;side++)
449         {
450                 for (y = 0;y < NORMSIZE;y++)
451                 {
452                         for (x = 0;x < NORMSIZE;x++)
453                         {
454                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
456                                 switch(side)
457                                 {
458                                 default:
459                                 case 0:
460                                         v[0] = 1;
461                                         v[1] = -t;
462                                         v[2] = -s;
463                                         break;
464                                 case 1:
465                                         v[0] = -1;
466                                         v[1] = -t;
467                                         v[2] = s;
468                                         break;
469                                 case 2:
470                                         v[0] = s;
471                                         v[1] = 1;
472                                         v[2] = t;
473                                         break;
474                                 case 3:
475                                         v[0] = s;
476                                         v[1] = -1;
477                                         v[2] = -t;
478                                         break;
479                                 case 4:
480                                         v[0] = s;
481                                         v[1] = -t;
482                                         v[2] = 1;
483                                         break;
484                                 case 5:
485                                         v[0] = -s;
486                                         v[1] = -t;
487                                         v[2] = -1;
488                                         break;
489                                 }
490                                 intensity = 127.0f / sqrt(DotProduct(v, v));
491                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494                                 data[((side*64+y)*64+x)*4+3] = 255;
495                         }
496                 }
497         }
498         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
499         Mem_Free(data);
500 }
501
502 static void R_BuildFogTexture(void)
503 {
504         int x, b;
505 #define FOGWIDTH 256
506         unsigned char data1[FOGWIDTH][4];
507         //unsigned char data2[FOGWIDTH][4];
508         double d, r, alpha;
509
510         r_refdef.fogmasktable_start = r_refdef.fog_start;
511         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512         r_refdef.fogmasktable_range = r_refdef.fogrange;
513         r_refdef.fogmasktable_density = r_refdef.fog_density;
514
515         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
517         {
518                 d = (x * r - r_refdef.fogmasktable_start);
519                 if(developer_extra.integer)
520                         Con_DPrintf("%f ", d);
521                 d = max(0, d);
522                 if (r_fog_exp2.integer)
523                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
524                 else
525                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526                 if(developer_extra.integer)
527                         Con_DPrintf(" : %f ", alpha);
528                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529                 if(developer_extra.integer)
530                         Con_DPrintf(" = %f\n", alpha);
531                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
532         }
533
534         for (x = 0;x < FOGWIDTH;x++)
535         {
536                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537                 data1[x][0] = b;
538                 data1[x][1] = b;
539                 data1[x][2] = b;
540                 data1[x][3] = 255;
541                 //data2[x][0] = 255 - b;
542                 //data2[x][1] = 255 - b;
543                 //data2[x][2] = 255 - b;
544                 //data2[x][3] = 255;
545         }
546         if (r_texture_fogattenuation)
547         {
548                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
550         }
551         else
552         {
553                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
555         }
556 }
557
558 static void R_BuildFogHeightTexture(void)
559 {
560         unsigned char *inpixels;
561         int size;
562         int x;
563         int y;
564         int j;
565         float c[4];
566         float f;
567         inpixels = NULL;
568         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569         if (r_refdef.fogheighttexturename[0])
570                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
571         if (!inpixels)
572         {
573                 r_refdef.fog_height_tablesize = 0;
574                 if (r_texture_fogheighttexture)
575                         R_FreeTexture(r_texture_fogheighttexture);
576                 r_texture_fogheighttexture = NULL;
577                 if (r_refdef.fog_height_table2d)
578                         Mem_Free(r_refdef.fog_height_table2d);
579                 r_refdef.fog_height_table2d = NULL;
580                 if (r_refdef.fog_height_table1d)
581                         Mem_Free(r_refdef.fog_height_table1d);
582                 r_refdef.fog_height_table1d = NULL;
583                 return;
584         }
585         size = image_width;
586         r_refdef.fog_height_tablesize = size;
587         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
590         Mem_Free(inpixels);
591         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
592         // average fog color table accounting for every fog layer between a point
593         // and the camera.  (Note: attenuation is handled separately!)
594         for (y = 0;y < size;y++)
595         {
596                 for (x = 0;x < size;x++)
597                 {
598                         Vector4Clear(c);
599                         f = 0;
600                         if (x < y)
601                         {
602                                 for (j = x;j <= y;j++)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         else
609                         {
610                                 for (j = x;j >= y;j--)
611                                 {
612                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613                                         f++;
614                                 }
615                         }
616                         f = 1.0f / f;
617                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
621                 }
622         }
623         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
624 }
625
626 //=======================================================================================================================================================
627
628 static const char *builtinshaderstrings[] =
629 {
630 #include "shader_glsl.h"
631 0
632 };
633
634 const char *builtinhlslshaderstrings[] =
635 {
636 #include "shader_hlsl.h"
637 0
638 };
639
640 char *glslshaderstring = NULL;
641 char *hlslshaderstring = NULL;
642
643 //=======================================================================================================================================================
644
645 typedef struct shaderpermutationinfo_s
646 {
647         const char *pretext;
648         const char *name;
649 }
650 shaderpermutationinfo_t;
651
652 typedef struct shadermodeinfo_s
653 {
654         const char *filename;
655         const char *pretext;
656         const char *name;
657 }
658 shadermodeinfo_t;
659
660 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
661 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
662 {
663         {"#define USEDIFFUSE\n", " diffuse"},
664         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
665         {"#define USEVIEWTINT\n", " viewtint"},
666         {"#define USECOLORMAPPING\n", " colormapping"},
667         {"#define USESATURATION\n", " saturation"},
668         {"#define USEFOGINSIDE\n", " foginside"},
669         {"#define USEFOGOUTSIDE\n", " fogoutside"},
670         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
671         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
672         {"#define USEGAMMARAMPS\n", " gammaramps"},
673         {"#define USECUBEFILTER\n", " cubefilter"},
674         {"#define USEGLOW\n", " glow"},
675         {"#define USEBLOOM\n", " bloom"},
676         {"#define USESPECULAR\n", " specular"},
677         {"#define USEPOSTPROCESSING\n", " postprocessing"},
678         {"#define USEREFLECTION\n", " reflection"},
679         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
680         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
681         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
682         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
683         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
684         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
685         {"#define USEALPHAKILL\n", " alphakill"},
686         {"#define USEREFLECTCUBE\n", " reflectcube"},
687         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
688         {"#define USEBOUNCEGRID\n", " bouncegrid"},
689         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
690         {"#define USETRIPPY\n", " trippy"},
691         {"#define USEDEPTHRGB\n", " depthrgb"},
692         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
693         {"#define USESKELETAL\n", " skeletal"},
694         {"#define USEOCCLUDE\n", " occlude"}
695 };
696
697 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
698 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
699 {
700         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
701         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
710         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
711         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
712         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
713         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
714         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
715         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
716         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
717 };
718
719 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
720 {
721         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
722         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
723         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
724         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
725         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
726         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
727         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
728         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
729         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
730         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
731         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
732         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
733         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
734         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
735         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
736         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
737         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
738 };
739
740 struct r_glsl_permutation_s;
741 typedef struct r_glsl_permutation_s
742 {
743         /// hash lookup data
744         struct r_glsl_permutation_s *hashnext;
745         unsigned int mode;
746         unsigned int permutation;
747
748         /// indicates if we have tried compiling this permutation already
749         qboolean compiled;
750         /// 0 if compilation failed
751         int program;
752         // texture units assigned to each detected uniform
753         int tex_Texture_First;
754         int tex_Texture_Second;
755         int tex_Texture_GammaRamps;
756         int tex_Texture_Normal;
757         int tex_Texture_Color;
758         int tex_Texture_Gloss;
759         int tex_Texture_Glow;
760         int tex_Texture_SecondaryNormal;
761         int tex_Texture_SecondaryColor;
762         int tex_Texture_SecondaryGloss;
763         int tex_Texture_SecondaryGlow;
764         int tex_Texture_Pants;
765         int tex_Texture_Shirt;
766         int tex_Texture_FogHeightTexture;
767         int tex_Texture_FogMask;
768         int tex_Texture_Lightmap;
769         int tex_Texture_Deluxemap;
770         int tex_Texture_Attenuation;
771         int tex_Texture_Cube;
772         int tex_Texture_Refraction;
773         int tex_Texture_Reflection;
774         int tex_Texture_ShadowMap2D;
775         int tex_Texture_CubeProjection;
776         int tex_Texture_ScreenNormalMap;
777         int tex_Texture_ScreenDiffuse;
778         int tex_Texture_ScreenSpecular;
779         int tex_Texture_ReflectMask;
780         int tex_Texture_ReflectCube;
781         int tex_Texture_BounceGrid;
782         /// locations of detected uniforms in program object, or -1 if not found
783         int loc_Texture_First;
784         int loc_Texture_Second;
785         int loc_Texture_GammaRamps;
786         int loc_Texture_Normal;
787         int loc_Texture_Color;
788         int loc_Texture_Gloss;
789         int loc_Texture_Glow;
790         int loc_Texture_SecondaryNormal;
791         int loc_Texture_SecondaryColor;
792         int loc_Texture_SecondaryGloss;
793         int loc_Texture_SecondaryGlow;
794         int loc_Texture_Pants;
795         int loc_Texture_Shirt;
796         int loc_Texture_FogHeightTexture;
797         int loc_Texture_FogMask;
798         int loc_Texture_Lightmap;
799         int loc_Texture_Deluxemap;
800         int loc_Texture_Attenuation;
801         int loc_Texture_Cube;
802         int loc_Texture_Refraction;
803         int loc_Texture_Reflection;
804         int loc_Texture_ShadowMap2D;
805         int loc_Texture_CubeProjection;
806         int loc_Texture_ScreenNormalMap;
807         int loc_Texture_ScreenDiffuse;
808         int loc_Texture_ScreenSpecular;
809         int loc_Texture_ReflectMask;
810         int loc_Texture_ReflectCube;
811         int loc_Texture_BounceGrid;
812         int loc_Alpha;
813         int loc_BloomBlur_Parameters;
814         int loc_ClientTime;
815         int loc_Color_Ambient;
816         int loc_Color_Diffuse;
817         int loc_Color_Specular;
818         int loc_Color_Glow;
819         int loc_Color_Pants;
820         int loc_Color_Shirt;
821         int loc_DeferredColor_Ambient;
822         int loc_DeferredColor_Diffuse;
823         int loc_DeferredColor_Specular;
824         int loc_DeferredMod_Diffuse;
825         int loc_DeferredMod_Specular;
826         int loc_DistortScaleRefractReflect;
827         int loc_EyePosition;
828         int loc_FogColor;
829         int loc_FogHeightFade;
830         int loc_FogPlane;
831         int loc_FogPlaneViewDist;
832         int loc_FogRangeRecip;
833         int loc_LightColor;
834         int loc_LightDir;
835         int loc_LightPosition;
836         int loc_OffsetMapping_ScaleSteps;
837         int loc_OffsetMapping_LodDistance;
838         int loc_OffsetMapping_Bias;
839         int loc_PixelSize;
840         int loc_ReflectColor;
841         int loc_ReflectFactor;
842         int loc_ReflectOffset;
843         int loc_RefractColor;
844         int loc_Saturation;
845         int loc_ScreenCenterRefractReflect;
846         int loc_ScreenScaleRefractReflect;
847         int loc_ScreenToDepth;
848         int loc_ShadowMap_Parameters;
849         int loc_ShadowMap_TextureScale;
850         int loc_SpecularPower;
851         int loc_Skeletal_Transform12;
852         int loc_UserVec1;
853         int loc_UserVec2;
854         int loc_UserVec3;
855         int loc_UserVec4;
856         int loc_ViewTintColor;
857         int loc_ViewToLight;
858         int loc_ModelToLight;
859         int loc_TexMatrix;
860         int loc_BackgroundTexMatrix;
861         int loc_ModelViewProjectionMatrix;
862         int loc_ModelViewMatrix;
863         int loc_PixelToScreenTexCoord;
864         int loc_ModelToReflectCube;
865         int loc_ShadowMapMatrix;
866         int loc_BloomColorSubtract;
867         int loc_NormalmapScrollBlend;
868         int loc_BounceGridMatrix;
869         int loc_BounceGridIntensity;
870         /// uniform block bindings
871         int ubibind_Skeletal_Transform12_UniformBlock;
872         /// uniform block indices
873         int ubiloc_Skeletal_Transform12_UniformBlock;
874 }
875 r_glsl_permutation_t;
876
877 #define SHADERPERMUTATION_HASHSIZE 256
878
879
880 // non-degradable "lightweight" shader parameters to keep the permutations simpler
881 // these can NOT degrade! only use for simple stuff
882 enum
883 {
884         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
885         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
886         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
887         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
888         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
889         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
890         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
891         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
892         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
893         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
894         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
895         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
896         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
897         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
898 };
899 #define SHADERSTATICPARMS_COUNT 14
900
901 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
902 static int shaderstaticparms_count = 0;
903
904 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
905 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
906
907 extern qboolean r_shadow_shadowmapsampler;
908 extern int r_shadow_shadowmappcf;
909 qboolean R_CompileShader_CheckStaticParms(void)
910 {
911         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
912         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
913         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
914
915         // detect all
916         if (r_glsl_saturation_redcompensate.integer)
917                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
918         if (r_glsl_vertextextureblend_usebothalphas.integer)
919                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
920         if (r_shadow_glossexact.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
922         if (r_glsl_postprocess.integer)
923         {
924                 if (r_glsl_postprocess_uservec1_enable.integer)
925                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
926                 if (r_glsl_postprocess_uservec2_enable.integer)
927                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
928                 if (r_glsl_postprocess_uservec3_enable.integer)
929                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
930                 if (r_glsl_postprocess_uservec4_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
932         }
933         if (r_fxaa.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
935         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
936                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
937
938         if (r_shadow_shadowmapsampler)
939                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
940         if (r_shadow_shadowmappcf > 1)
941                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
942         else if (r_shadow_shadowmappcf)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
944         if (r_celshading.integer)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
946         if (r_celoutlines.integer)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
948
949         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
950 }
951
952 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
953         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
954                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
955         else \
956                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
957 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
958 {
959         shaderstaticparms_count = 0;
960
961         // emit all
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
963         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
964         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
965         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
976 }
977
978 /// information about each possible shader permutation
979 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
980 /// currently selected permutation
981 r_glsl_permutation_t *r_glsl_permutation;
982 /// storage for permutations linked in the hash table
983 memexpandablearray_t r_glsl_permutationarray;
984
985 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
986 {
987         //unsigned int hashdepth = 0;
988         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
989         r_glsl_permutation_t *p;
990         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
991         {
992                 if (p->mode == mode && p->permutation == permutation)
993                 {
994                         //if (hashdepth > 10)
995                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
996                         return p;
997                 }
998                 //hashdepth++;
999         }
1000         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1001         p->mode = mode;
1002         p->permutation = permutation;
1003         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1004         r_glsl_permutationhash[mode][hashindex] = p;
1005         //if (hashdepth > 10)
1006         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1007         return p;
1008 }
1009
1010 static char *R_ShaderStrCat(const char **strings)
1011 {
1012         char *string, *s;
1013         const char **p = strings;
1014         const char *t;
1015         size_t len = 0;
1016         for (p = strings;(t = *p);p++)
1017                 len += strlen(t);
1018         len++;
1019         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1020         len = 0;
1021         for (p = strings;(t = *p);p++)
1022         {
1023                 len = strlen(t);
1024                 memcpy(s, t, len);
1025                 s += len;
1026         }
1027         *s = 0;
1028         return string;
1029 }
1030
1031 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1032 {
1033         char *shaderstring;
1034         if (!filename || !filename[0])
1035                 return NULL;
1036         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1037         if (!strcmp(filename, "glsl/default.glsl"))
1038         {
1039                 if (builtinonly)
1040                         return R_ShaderStrCat(builtinshaderstrings);
1041                 if (!glslshaderstring)
1042                 {
1043                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1044                         if (glslshaderstring)
1045                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046                         else
1047                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1048                 }
1049                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1050                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1051                 return shaderstring;
1052         }
1053         if (!strcmp(filename, "hlsl/default.hlsl"))
1054         {
1055                 if (builtinonly)
1056                         return R_ShaderStrCat(builtinhlslshaderstrings);
1057                 if (!hlslshaderstring)
1058                 {
1059                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1060                         if (hlslshaderstring)
1061                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1062                         else
1063                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1064                 }
1065                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1066                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1067                 return shaderstring;
1068         }
1069         // we don't have builtin strings for any other files
1070         if (builtinonly)
1071                 return NULL;
1072         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1073         if (shaderstring)
1074         {
1075                 if (printfromdisknotice)
1076                         Con_DPrintf("from disk %s... ", filename);
1077                 return shaderstring;
1078         }
1079         return shaderstring;
1080 }
1081
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1083 {
1084         int i;
1085         int ubibind;
1086         int sampler;
1087         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1088         char *sourcestring;
1089         char permutationname[256];
1090         int vertstrings_count = 0;
1091         int geomstrings_count = 0;
1092         int fragstrings_count = 0;
1093         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096
1097         if (p->compiled)
1098                 return;
1099         p->compiled = true;
1100         p->program = 0;
1101
1102         permutationname[0] = 0;
1103         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1104
1105         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106
1107         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108         if(vid.support.glshaderversion >= 140)
1109         {
1110                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116         }
1117         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118         else if(vid.support.glshaderversion >= 130)
1119         {
1120                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126         }
1127
1128         // the first pretext is which type of shader to compile as
1129         // (later these will all be bound together as a program object)
1130         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1131         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1132         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1133
1134         // the second pretext is the mode (for example a light source)
1135         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1136         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1137         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1138         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1139
1140         // now add all the permutation pretexts
1141         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1142         {
1143                 if (permutation & (1<<i))
1144                 {
1145                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1146                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1147                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1148                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1149                 }
1150                 else
1151                 {
1152                         // keep line numbers correct
1153                         vertstrings_list[vertstrings_count++] = "\n";
1154                         geomstrings_list[geomstrings_count++] = "\n";
1155                         fragstrings_list[fragstrings_count++] = "\n";
1156                 }
1157         }
1158
1159         // add static parms
1160         R_CompileShader_AddStaticParms(mode, permutation);
1161         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162         vertstrings_count += shaderstaticparms_count;
1163         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1164         geomstrings_count += shaderstaticparms_count;
1165         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1166         fragstrings_count += shaderstaticparms_count;
1167
1168         // now append the shader text itself
1169         vertstrings_list[vertstrings_count++] = sourcestring;
1170         geomstrings_list[geomstrings_count++] = sourcestring;
1171         fragstrings_list[fragstrings_count++] = sourcestring;
1172
1173         // compile the shader program
1174         if (vertstrings_count + geomstrings_count + fragstrings_count)
1175                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1176         if (p->program)
1177         {
1178                 CHECKGLERROR
1179                 qglUseProgram(p->program);CHECKGLERROR
1180                 // look up all the uniform variable names we care about, so we don't
1181                 // have to look them up every time we set them
1182
1183 #if 0
1184                 // debugging aid
1185                 {
1186                         GLint activeuniformindex = 0;
1187                         GLint numactiveuniforms = 0;
1188                         char uniformname[128];
1189                         GLsizei uniformnamelength = 0;
1190                         GLint uniformsize = 0;
1191                         GLenum uniformtype = 0;
1192                         memset(uniformname, 0, sizeof(uniformname));
1193                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1194                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1195                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1196                         {
1197                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1198                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1199                         }
1200                 }
1201 #endif
1202
1203                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1204                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1205                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1206                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1207                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1208                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1209                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1210                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1211                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1212                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1213                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1214                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1215                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1216                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1217                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1218                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1219                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1220                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1221                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1222                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1223                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1224                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1225                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1226                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1227                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1228                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1229                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1230                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1231                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1232                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1233                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1234                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1235                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1236                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1237                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1238                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1239                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1240                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1241                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1242                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1243                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1244                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1245                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1246                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1247                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1248                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1249                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1250                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1251                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1252                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1253                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1254                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1255                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1256                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1257                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1258                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1259                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1260                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1261                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1262                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1263                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1264                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1265                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1266                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1267                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1268                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1269                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1270                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1271                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1272                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1273                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1274                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1275                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1276                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1277                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1278                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1279                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1280                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1281                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1282                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1283                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1284                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1285                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1286                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1287                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1288                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1289                 // initialize the samplers to refer to the texture units we use
1290                 p->tex_Texture_First = -1;
1291                 p->tex_Texture_Second = -1;
1292                 p->tex_Texture_GammaRamps = -1;
1293                 p->tex_Texture_Normal = -1;
1294                 p->tex_Texture_Color = -1;
1295                 p->tex_Texture_Gloss = -1;
1296                 p->tex_Texture_Glow = -1;
1297                 p->tex_Texture_SecondaryNormal = -1;
1298                 p->tex_Texture_SecondaryColor = -1;
1299                 p->tex_Texture_SecondaryGloss = -1;
1300                 p->tex_Texture_SecondaryGlow = -1;
1301                 p->tex_Texture_Pants = -1;
1302                 p->tex_Texture_Shirt = -1;
1303                 p->tex_Texture_FogHeightTexture = -1;
1304                 p->tex_Texture_FogMask = -1;
1305                 p->tex_Texture_Lightmap = -1;
1306                 p->tex_Texture_Deluxemap = -1;
1307                 p->tex_Texture_Attenuation = -1;
1308                 p->tex_Texture_Cube = -1;
1309                 p->tex_Texture_Refraction = -1;
1310                 p->tex_Texture_Reflection = -1;
1311                 p->tex_Texture_ShadowMap2D = -1;
1312                 p->tex_Texture_CubeProjection = -1;
1313                 p->tex_Texture_ScreenNormalMap = -1;
1314                 p->tex_Texture_ScreenDiffuse = -1;
1315                 p->tex_Texture_ScreenSpecular = -1;
1316                 p->tex_Texture_ReflectMask = -1;
1317                 p->tex_Texture_ReflectCube = -1;
1318                 p->tex_Texture_BounceGrid = -1;
1319                 // bind the texture samplers in use
1320                 sampler = 0;
1321                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1322                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1323                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1324                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1325                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1326                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1327                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1328                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1329                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1330                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1331                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1332                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1333                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1334                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1335                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1336                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1337                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1338                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1339                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1340                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1341                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1342                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1343                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1344                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1345                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1346                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1347                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1348                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1349                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1350                 // get the uniform block indices so we can bind them
1351 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1352                 if (vid.support.arb_uniform_buffer_object)
1353                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1354                 else
1355 #endif
1356                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1357                 // clear the uniform block bindings
1358                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1359                 // bind the uniform blocks in use
1360                 ubibind = 0;
1361 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1362                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1363 #endif
1364                 // we're done compiling and setting up the shader, at least until it is used
1365                 CHECKGLERROR
1366                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1367         }
1368         else
1369                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1370
1371         // free the strings
1372         if (sourcestring)
1373                 Mem_Free(sourcestring);
1374 }
1375
1376 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1377 {
1378         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1379         if (r_glsl_permutation != perm)
1380         {
1381                 r_glsl_permutation = perm;
1382                 if (!r_glsl_permutation->program)
1383                 {
1384                         if (!r_glsl_permutation->compiled)
1385                         {
1386                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1387                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1388                         }
1389                         if (!r_glsl_permutation->program)
1390                         {
1391                                 // remove features until we find a valid permutation
1392                                 int i;
1393                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1394                                 {
1395                                         // reduce i more quickly whenever it would not remove any bits
1396                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1397                                         if (!(permutation & j))
1398                                                 continue;
1399                                         permutation -= j;
1400                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401                                         if (!r_glsl_permutation->compiled)
1402                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1403                                         if (r_glsl_permutation->program)
1404                                                 break;
1405                                 }
1406                                 if (i >= SHADERPERMUTATION_COUNT)
1407                                 {
1408                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1409                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1410                                         qglUseProgram(0);CHECKGLERROR
1411                                         return; // no bit left to clear, entire mode is broken
1412                                 }
1413                         }
1414                 }
1415                 CHECKGLERROR
1416                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1417         }
1418         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1419         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1420         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1421         CHECKGLERROR
1422 }
1423
1424 #ifdef SUPPORTD3D
1425
1426 #ifdef SUPPORTD3D
1427 #include <d3d9.h>
1428 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1429 extern D3DCAPS9 vid_d3d9caps;
1430 #endif
1431
1432 struct r_hlsl_permutation_s;
1433 typedef struct r_hlsl_permutation_s
1434 {
1435         /// hash lookup data
1436         struct r_hlsl_permutation_s *hashnext;
1437         unsigned int mode;
1438         unsigned int permutation;
1439
1440         /// indicates if we have tried compiling this permutation already
1441         qboolean compiled;
1442         /// NULL if compilation failed
1443         IDirect3DVertexShader9 *vertexshader;
1444         IDirect3DPixelShader9 *pixelshader;
1445 }
1446 r_hlsl_permutation_t;
1447
1448 typedef enum D3DVSREGISTER_e
1449 {
1450         D3DVSREGISTER_TexMatrix = 0, // float4x4
1451         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1452         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1453         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1454         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1455         D3DVSREGISTER_ModelToLight = 20, // float4x4
1456         D3DVSREGISTER_EyePosition = 24,
1457         D3DVSREGISTER_FogPlane = 25,
1458         D3DVSREGISTER_LightDir = 26,
1459         D3DVSREGISTER_LightPosition = 27,
1460 }
1461 D3DVSREGISTER_t;
1462
1463 typedef enum D3DPSREGISTER_e
1464 {
1465         D3DPSREGISTER_Alpha = 0,
1466         D3DPSREGISTER_BloomBlur_Parameters = 1,
1467         D3DPSREGISTER_ClientTime = 2,
1468         D3DPSREGISTER_Color_Ambient = 3,
1469         D3DPSREGISTER_Color_Diffuse = 4,
1470         D3DPSREGISTER_Color_Specular = 5,
1471         D3DPSREGISTER_Color_Glow = 6,
1472         D3DPSREGISTER_Color_Pants = 7,
1473         D3DPSREGISTER_Color_Shirt = 8,
1474         D3DPSREGISTER_DeferredColor_Ambient = 9,
1475         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1476         D3DPSREGISTER_DeferredColor_Specular = 11,
1477         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1478         D3DPSREGISTER_DeferredMod_Specular = 13,
1479         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1480         D3DPSREGISTER_EyePosition = 15, // unused
1481         D3DPSREGISTER_FogColor = 16,
1482         D3DPSREGISTER_FogHeightFade = 17,
1483         D3DPSREGISTER_FogPlane = 18,
1484         D3DPSREGISTER_FogPlaneViewDist = 19,
1485         D3DPSREGISTER_FogRangeRecip = 20,
1486         D3DPSREGISTER_LightColor = 21,
1487         D3DPSREGISTER_LightDir = 22, // unused
1488         D3DPSREGISTER_LightPosition = 23,
1489         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1490         D3DPSREGISTER_PixelSize = 25,
1491         D3DPSREGISTER_ReflectColor = 26,
1492         D3DPSREGISTER_ReflectFactor = 27,
1493         D3DPSREGISTER_ReflectOffset = 28,
1494         D3DPSREGISTER_RefractColor = 29,
1495         D3DPSREGISTER_Saturation = 30,
1496         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1497         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1498         D3DPSREGISTER_ScreenToDepth = 33,
1499         D3DPSREGISTER_ShadowMap_Parameters = 34,
1500         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1501         D3DPSREGISTER_SpecularPower = 36,
1502         D3DPSREGISTER_UserVec1 = 37,
1503         D3DPSREGISTER_UserVec2 = 38,
1504         D3DPSREGISTER_UserVec3 = 39,
1505         D3DPSREGISTER_UserVec4 = 40,
1506         D3DPSREGISTER_ViewTintColor = 41,
1507         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1508         D3DPSREGISTER_BloomColorSubtract = 43,
1509         D3DPSREGISTER_ViewToLight = 44, // float4x4
1510         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1511         D3DPSREGISTER_NormalmapScrollBlend = 52,
1512         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1513         D3DPSREGISTER_OffsetMapping_Bias = 54,
1514         // next at 54
1515 }
1516 D3DPSREGISTER_t;
1517
1518 /// information about each possible shader permutation
1519 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1520 /// currently selected permutation
1521 r_hlsl_permutation_t *r_hlsl_permutation;
1522 /// storage for permutations linked in the hash table
1523 memexpandablearray_t r_hlsl_permutationarray;
1524
1525 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1526 {
1527         //unsigned int hashdepth = 0;
1528         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1529         r_hlsl_permutation_t *p;
1530         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1531         {
1532                 if (p->mode == mode && p->permutation == permutation)
1533                 {
1534                         //if (hashdepth > 10)
1535                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1536                         return p;
1537                 }
1538                 //hashdepth++;
1539         }
1540         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1541         p->mode = mode;
1542         p->permutation = permutation;
1543         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1544         r_hlsl_permutationhash[mode][hashindex] = p;
1545         //if (hashdepth > 10)
1546         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1547         return p;
1548 }
1549
1550 #include <d3dx9.h>
1551 //#include <d3dx9shader.h>
1552 //#include <d3dx9mesh.h>
1553
1554 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1555 {
1556         DWORD *vsbin = NULL;
1557         DWORD *psbin = NULL;
1558         fs_offset_t vsbinsize;
1559         fs_offset_t psbinsize;
1560 //      IDirect3DVertexShader9 *vs = NULL;
1561 //      IDirect3DPixelShader9 *ps = NULL;
1562         ID3DXBuffer *vslog = NULL;
1563         ID3DXBuffer *vsbuffer = NULL;
1564         ID3DXConstantTable *vsconstanttable = NULL;
1565         ID3DXBuffer *pslog = NULL;
1566         ID3DXBuffer *psbuffer = NULL;
1567         ID3DXConstantTable *psconstanttable = NULL;
1568         int vsresult = 0;
1569         int psresult = 0;
1570         char temp[MAX_INPUTLINE];
1571         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1572         char vabuf[1024];
1573         qboolean debugshader = gl_paranoid.integer != 0;
1574         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1575         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1576         if (!debugshader)
1577         {
1578                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1579                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1580         }
1581         if ((!vsbin && vertstring) || (!psbin && fragstring))
1582         {
1583                 const char* dllnames_d3dx9 [] =
1584                 {
1585                         "d3dx9_43.dll",
1586                         "d3dx9_42.dll",
1587                         "d3dx9_41.dll",
1588                         "d3dx9_40.dll",
1589                         "d3dx9_39.dll",
1590                         "d3dx9_38.dll",
1591                         "d3dx9_37.dll",
1592                         "d3dx9_36.dll",
1593                         "d3dx9_35.dll",
1594                         "d3dx9_34.dll",
1595                         "d3dx9_33.dll",
1596                         "d3dx9_32.dll",
1597                         "d3dx9_31.dll",
1598                         "d3dx9_30.dll",
1599                         "d3dx9_29.dll",
1600                         "d3dx9_28.dll",
1601                         "d3dx9_27.dll",
1602                         "d3dx9_26.dll",
1603                         "d3dx9_25.dll",
1604                         "d3dx9_24.dll",
1605                         NULL
1606                 };
1607                 dllhandle_t d3dx9_dll = NULL;
1608                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1609                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1610                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1611                 dllfunction_t d3dx9_dllfuncs[] =
1612                 {
1613                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1614                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1615                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1616                         {NULL, NULL}
1617                 };
1618                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1619 #ifndef ID3DXBuffer_GetBufferPointer
1620 #if !defined(__cplusplus) || defined(CINTERFACE)
1621 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1622 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1623 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1624 #else
1625 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1626 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1627 #define ID3DXBuffer_Release(p)            (p)->Release()
1628 #endif
1629 #endif
1630                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1631                 {
1632                         DWORD shaderflags = 0;
1633                         if (debugshader)
1634                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1635                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1636                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1637                         if (vertstring && vertstring[0])
1638                         {
1639                                 if (debugshader)
1640                                 {
1641                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1642                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1643                                 }
1644                                 else
1645                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1646                                 if (vsbuffer)
1647                                 {
1648                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1649                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1650                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1651                                         ID3DXBuffer_Release(vsbuffer);
1652                                 }
1653                                 if (vslog)
1654                                 {
1655                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1656                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1657                                         ID3DXBuffer_Release(vslog);
1658                                 }
1659                         }
1660                         if (fragstring && fragstring[0])
1661                         {
1662                                 if (debugshader)
1663                                 {
1664                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1665                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1666                                 }
1667                                 else
1668                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1669                                 if (psbuffer)
1670                                 {
1671                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1672                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1673                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1674                                         ID3DXBuffer_Release(psbuffer);
1675                                 }
1676                                 if (pslog)
1677                                 {
1678                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1679                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1680                                         ID3DXBuffer_Release(pslog);
1681                                 }
1682                         }
1683                         Sys_UnloadLibrary(&d3dx9_dll);
1684                 }
1685                 else
1686                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1687         }
1688         if (vsbin && psbin)
1689         {
1690                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1691                 if (FAILED(vsresult))
1692                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1693                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1694                 if (FAILED(psresult))
1695                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1696         }
1697         // free the shader data
1698         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1699         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1700 }
1701
1702 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1703 {
1704         int i;
1705         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1706         int vertstring_length = 0;
1707         int geomstring_length = 0;
1708         int fragstring_length = 0;
1709         char *t;
1710         char *sourcestring;
1711         char *vertstring, *geomstring, *fragstring;
1712         char permutationname[256];
1713         char cachename[256];
1714         int vertstrings_count = 0;
1715         int geomstrings_count = 0;
1716         int fragstrings_count = 0;
1717         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1718         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1719         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1720
1721         if (p->compiled)
1722                 return;
1723         p->compiled = true;
1724         p->vertexshader = NULL;
1725         p->pixelshader = NULL;
1726
1727         permutationname[0] = 0;
1728         cachename[0] = 0;
1729         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1730
1731         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1732         strlcat(cachename, "hlsl/", sizeof(cachename));
1733
1734         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1735         vertstrings_count = 0;
1736         geomstrings_count = 0;
1737         fragstrings_count = 0;
1738         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1739         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1740         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1741
1742         // the first pretext is which type of shader to compile as
1743         // (later these will all be bound together as a program object)
1744         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1745         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1746         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1747
1748         // the second pretext is the mode (for example a light source)
1749         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1750         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1751         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1752         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1753         strlcat(cachename, modeinfo->name, sizeof(cachename));
1754
1755         // now add all the permutation pretexts
1756         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1757         {
1758                 if (permutation & (1<<i))
1759                 {
1760                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1761                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1762                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1763                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1764                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1765                 }
1766                 else
1767                 {
1768                         // keep line numbers correct
1769                         vertstrings_list[vertstrings_count++] = "\n";
1770                         geomstrings_list[geomstrings_count++] = "\n";
1771                         fragstrings_list[fragstrings_count++] = "\n";
1772                 }
1773         }
1774
1775         // add static parms
1776         R_CompileShader_AddStaticParms(mode, permutation);
1777         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778         vertstrings_count += shaderstaticparms_count;
1779         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1780         geomstrings_count += shaderstaticparms_count;
1781         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1782         fragstrings_count += shaderstaticparms_count;
1783
1784         // replace spaces in the cachename with _ characters
1785         for (i = 0;cachename[i];i++)
1786                 if (cachename[i] == ' ')
1787                         cachename[i] = '_';
1788
1789         // now append the shader text itself
1790         vertstrings_list[vertstrings_count++] = sourcestring;
1791         geomstrings_list[geomstrings_count++] = sourcestring;
1792         fragstrings_list[fragstrings_count++] = sourcestring;
1793
1794         vertstring_length = 0;
1795         for (i = 0;i < vertstrings_count;i++)
1796                 vertstring_length += (int)strlen(vertstrings_list[i]);
1797         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1798         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1799                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1800
1801         geomstring_length = 0;
1802         for (i = 0;i < geomstrings_count;i++)
1803                 geomstring_length += (int)strlen(geomstrings_list[i]);
1804         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1805         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1806                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1807
1808         fragstring_length = 0;
1809         for (i = 0;i < fragstrings_count;i++)
1810                 fragstring_length += (int)strlen(fragstrings_list[i]);
1811         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1812         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1813                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1814
1815         // try to load the cached shader, or generate one
1816         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1817
1818         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1819                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1820         else
1821                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1822
1823         // free the strings
1824         if (vertstring)
1825                 Mem_Free(vertstring);
1826         if (geomstring)
1827                 Mem_Free(geomstring);
1828         if (fragstring)
1829                 Mem_Free(fragstring);
1830         if (sourcestring)
1831                 Mem_Free(sourcestring);
1832 }
1833
1834 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1835 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1836 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);}
1837 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);}
1838 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);}
1839 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);}
1840
1841 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1842 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1843 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);}
1844 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);}
1845 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);}
1846 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);}
1847
1848 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1849 {
1850         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1851         if (r_hlsl_permutation != perm)
1852         {
1853                 r_hlsl_permutation = perm;
1854                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1855                 {
1856                         if (!r_hlsl_permutation->compiled)
1857                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1858                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1859                         {
1860                                 // remove features until we find a valid permutation
1861                                 int i;
1862                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1863                                 {
1864                                         // reduce i more quickly whenever it would not remove any bits
1865                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1866                                         if (!(permutation & j))
1867                                                 continue;
1868                                         permutation -= j;
1869                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870                                         if (!r_hlsl_permutation->compiled)
1871                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1872                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1873                                                 break;
1874                                 }
1875                                 if (i >= SHADERPERMUTATION_COUNT)
1876                                 {
1877                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1878                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1879                                         return; // no bit left to clear, entire mode is broken
1880                                 }
1881                         }
1882                 }
1883                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1884                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1885         }
1886         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1887         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1888         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1889 }
1890 #endif
1891
1892 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1893 {
1894         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1895         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1896         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1897         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1898 }
1899
1900 void R_GLSL_Restart_f(void)
1901 {
1902         unsigned int i, limit;
1903         if (glslshaderstring)
1904                 Mem_Free(glslshaderstring);
1905         glslshaderstring = NULL;
1906         if (hlslshaderstring)
1907                 Mem_Free(hlslshaderstring);
1908         hlslshaderstring = NULL;
1909         switch(vid.renderpath)
1910         {
1911         case RENDERPATH_D3D9:
1912 #ifdef SUPPORTD3D
1913                 {
1914                         r_hlsl_permutation_t *p;
1915                         r_hlsl_permutation = NULL;
1916                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1917                         for (i = 0;i < limit;i++)
1918                         {
1919                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1920                                 {
1921                                         if (p->vertexshader)
1922                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1923                                         if (p->pixelshader)
1924                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1925                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1926                                 }
1927                         }
1928                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1929                 }
1930 #endif
1931                 break;
1932         case RENDERPATH_D3D10:
1933                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934                 break;
1935         case RENDERPATH_D3D11:
1936                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1937                 break;
1938         case RENDERPATH_GL20:
1939         case RENDERPATH_GLES2:
1940                 {
1941                         r_glsl_permutation_t *p;
1942                         r_glsl_permutation = NULL;
1943                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1944                         for (i = 0;i < limit;i++)
1945                         {
1946                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1947                                 {
1948                                         GL_Backend_FreeProgram(p->program);
1949                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1950                                 }
1951                         }
1952                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1953                 }
1954                 break;
1955         case RENDERPATH_GL11:
1956         case RENDERPATH_GL13:
1957         case RENDERPATH_GLES1:
1958                 break;
1959         case RENDERPATH_SOFT:
1960                 break;
1961         }
1962 }
1963
1964 static void R_GLSL_DumpShader_f(void)
1965 {
1966         int i, language, mode, dupe;
1967         char *text;
1968         shadermodeinfo_t *modeinfo;
1969         qfile_t *file;
1970
1971         for (language = 0;language < 2;language++)
1972         {
1973                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1974                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1975                 {
1976                         // don't dump the same file multiple times (most or all shaders come from the same file)
1977                         for (dupe = mode - 1;dupe >= 0;dupe--)
1978                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1979                                         break;
1980                         if (dupe >= 0)
1981                                 continue;
1982                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1983                         if (!text)
1984                                 continue;
1985                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1986                         if (file)
1987                         {
1988                                 FS_Print(file, "/* The engine may define the following macros:\n");
1989                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1991                                         FS_Print(file, modeinfo[i].pretext);
1992                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1994                                 FS_Print(file, "*/\n");
1995                                 FS_Print(file, text);
1996                                 FS_Close(file);
1997                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1998                         }
1999                         else
2000                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2001                         Mem_Free(text);
2002                 }
2003         }
2004 }
2005
2006 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2007 {
2008         unsigned int permutation = 0;
2009         if (r_trippy.integer && !notrippy)
2010                 permutation |= SHADERPERMUTATION_TRIPPY;
2011         permutation |= SHADERPERMUTATION_VIEWTINT;
2012         if (first)
2013                 permutation |= SHADERPERMUTATION_DIFFUSE;
2014         if (second)
2015                 permutation |= SHADERPERMUTATION_SPECULAR;
2016         if (texturemode == GL_MODULATE)
2017                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2018         else if (texturemode == GL_ADD)
2019                 permutation |= SHADERPERMUTATION_GLOW;
2020         else if (texturemode == GL_DECAL)
2021                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2022         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2023                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2024         if (suppresstexalpha)
2025                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2026         if (!second)
2027                 texturemode = GL_MODULATE;
2028         if (vid.allowalphatocoverage)
2029                 GL_AlphaToCoverage(false);
2030         switch (vid.renderpath)
2031         {
2032         case RENDERPATH_D3D9:
2033 #ifdef SUPPORTD3D
2034                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2035                 R_Mesh_TexBind(GL20TU_FIRST , first );
2036                 R_Mesh_TexBind(GL20TU_SECOND, second);
2037                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2038                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2039 #endif
2040                 break;
2041         case RENDERPATH_D3D10:
2042                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043                 break;
2044         case RENDERPATH_D3D11:
2045                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2046                 break;
2047         case RENDERPATH_GL20:
2048         case RENDERPATH_GLES2:
2049                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2050                 if (r_glsl_permutation->tex_Texture_First >= 0)
2051                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2052                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2053                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2054                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2055                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2056                 break;
2057         case RENDERPATH_GL13:
2058         case RENDERPATH_GLES1:
2059                 R_Mesh_TexBind(0, first );
2060                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061                 R_Mesh_TexMatrix(0, NULL);
2062                 R_Mesh_TexBind(1, second);
2063                 if (second)
2064                 {
2065                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2066                         R_Mesh_TexMatrix(1, NULL);
2067                 }
2068                 break;
2069         case RENDERPATH_GL11:
2070                 R_Mesh_TexBind(0, first );
2071                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2072                 R_Mesh_TexMatrix(0, NULL);
2073                 break;
2074         case RENDERPATH_SOFT:
2075                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2076                 R_Mesh_TexBind(GL20TU_FIRST , first );
2077                 R_Mesh_TexBind(GL20TU_SECOND, second);
2078                 break;
2079         }
2080 }
2081
2082 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2083 {
2084         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2085 }
2086
2087 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2088 {
2089         unsigned int permutation = 0;
2090         if (r_trippy.integer && !notrippy)
2091                 permutation |= SHADERPERMUTATION_TRIPPY;
2092         if (depthrgb)
2093                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2094         if (skeletal)
2095                 permutation |= SHADERPERMUTATION_SKELETAL;
2096
2097         if (vid.allowalphatocoverage)
2098                 GL_AlphaToCoverage(false);
2099         switch (vid.renderpath)
2100         {
2101         case RENDERPATH_D3D9:
2102 #ifdef SUPPORTD3D
2103                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2104 #endif
2105                 break;
2106         case RENDERPATH_D3D10:
2107                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2108                 break;
2109         case RENDERPATH_D3D11:
2110                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2111                 break;
2112         case RENDERPATH_GL20:
2113         case RENDERPATH_GLES2:
2114                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2116                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2117 #endif
2118                 break;
2119         case RENDERPATH_GL13:
2120         case RENDERPATH_GLES1:
2121                 R_Mesh_TexBind(0, 0);
2122                 R_Mesh_TexBind(1, 0);
2123                 break;
2124         case RENDERPATH_GL11:
2125                 R_Mesh_TexBind(0, 0);
2126                 break;
2127         case RENDERPATH_SOFT:
2128                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129                 break;
2130         }
2131 }
2132
2133 extern qboolean r_shadow_usingdeferredprepass;
2134 extern rtexture_t *r_shadow_attenuationgradienttexture;
2135 extern rtexture_t *r_shadow_attenuation2dtexture;
2136 extern rtexture_t *r_shadow_attenuation3dtexture;
2137 extern qboolean r_shadow_usingshadowmap2d;
2138 extern qboolean r_shadow_usingshadowmaportho;
2139 extern float r_shadow_shadowmap_texturescale[2];
2140 extern float r_shadow_shadowmap_parameters[4];
2141 extern qboolean r_shadow_shadowmapvsdct;
2142 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2143 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2144 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2145 extern matrix4x4_t r_shadow_shadowmapmatrix;
2146 extern int r_shadow_prepass_width;
2147 extern int r_shadow_prepass_height;
2148 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2149 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2150 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2151 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2152
2153 #define BLENDFUNC_ALLOWS_COLORMOD      1
2154 #define BLENDFUNC_ALLOWS_FOG           2
2155 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2156 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2157 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2158 static int R_BlendFuncFlags(int src, int dst)
2159 {
2160         int r = 0;
2161
2162         // a blendfunc allows colormod if:
2163         // a) it can never keep the destination pixel invariant, or
2164         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2165         // this is to prevent unintended side effects from colormod
2166
2167         // a blendfunc allows fog if:
2168         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2169         // this is to prevent unintended side effects from fog
2170
2171         // these checks are the output of fogeval.pl
2172
2173         r |= BLENDFUNC_ALLOWS_COLORMOD;
2174         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2176         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2182         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2183         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2184         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2185         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2186         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2187         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2188         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2189         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2193         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195
2196         return r;
2197 }
2198
2199 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)
2200 {
2201         // select a permutation of the lighting shader appropriate to this
2202         // combination of texture, entity, light source, and fogging, only use the
2203         // minimum features necessary to avoid wasting rendering time in the
2204         // fragment shader on features that are not being used
2205         unsigned int permutation = 0;
2206         unsigned int mode = 0;
2207         int blendfuncflags;
2208         static float dummy_colormod[3] = {1, 1, 1};
2209         float *colormod = rsurface.colormod;
2210         float m16f[16];
2211         matrix4x4_t tempmatrix;
2212         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2213         if (r_trippy.integer && !notrippy)
2214                 permutation |= SHADERPERMUTATION_TRIPPY;
2215         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2216                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2217         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2218                 permutation |= SHADERPERMUTATION_OCCLUDE;
2219         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2220                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2221         if (rsurfacepass == RSURFPASS_BACKGROUND)
2222         {
2223                 // distorted background
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2225                 {
2226                         mode = SHADERMODE_WATER;
2227                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2230                         {
2231                                 // this is the right thing to do for wateralpha
2232                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2233                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2234                         }
2235                         else
2236                         {
2237                                 // this is the right thing to do for entity alpha
2238                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240                         }
2241                 }
2242                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2243                 {
2244                         mode = SHADERMODE_REFRACTION;
2245                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2246                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2247                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2248                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249                 }
2250                 else
2251                 {
2252                         mode = SHADERMODE_GENERIC;
2253                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2254                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                 }
2257                 if (vid.allowalphatocoverage)
2258                         GL_AlphaToCoverage(false);
2259         }
2260         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2261         {
2262                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2263                 {
2264                         switch(rsurface.texture->offsetmapping)
2265                         {
2266                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2267                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2268                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269                         case OFFSETMAPPING_OFF: break;
2270                         }
2271                 }
2272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2273                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2274                 // normalmap (deferred prepass), may use alpha test on diffuse
2275                 mode = SHADERMODE_DEFERREDGEOMETRY;
2276                 GL_BlendFunc(GL_ONE, GL_ZERO);
2277                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2278                 if (vid.allowalphatocoverage)
2279                         GL_AlphaToCoverage(false);
2280         }
2281         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2282         {
2283                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2284                 {
2285                         switch(rsurface.texture->offsetmapping)
2286                         {
2287                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2288                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_OFF: break;
2291                         }
2292                 }
2293                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2294                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2295                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2296                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2297                 // light source
2298                 mode = SHADERMODE_LIGHTSOURCE;
2299                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2300                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2301                 if (diffusescale > 0)
2302                         permutation |= SHADERPERMUTATION_DIFFUSE;
2303                 if (specularscale > 0)
2304                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmap2d)
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312                         if(r_shadow_shadowmapvsdct)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2314
2315                         if (r_shadow_shadowmap2ddepthbuffer)
2316                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2317                 }
2318                 if (rsurface.texture->reflectmasktexture)
2319                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2321                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2322                 if (vid.allowalphatocoverage)
2323                         GL_AlphaToCoverage(false);
2324         }
2325         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2326         {
2327                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2328                 {
2329                         switch(rsurface.texture->offsetmapping)
2330                         {
2331                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2332                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2333                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334                         case OFFSETMAPPING_OFF: break;
2335                         }
2336                 }
2337                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2338                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2340                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2341                 // unshaded geometry (fullbright or ambient model lighting)
2342                 mode = SHADERMODE_FLATCOLOR;
2343                 ambientscale = diffusescale = specularscale = 0;
2344                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2345                         permutation |= SHADERPERMUTATION_GLOW;
2346                 if (r_refdef.fogenabled)
2347                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2348                 if (rsurface.texture->colormapping)
2349                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2350                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2351                 {
2352                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2353                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2354
2355                         if (r_shadow_shadowmap2ddepthbuffer)
2356                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2357                 }
2358                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2359                         permutation |= SHADERPERMUTATION_REFLECTION;
2360                 if (rsurface.texture->reflectmasktexture)
2361                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2362                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2363                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2364                 // when using alphatocoverage, we don't need alphakill
2365                 if (vid.allowalphatocoverage)
2366                 {
2367                         if (r_transparent_alphatocoverage.integer)
2368                         {
2369                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2370                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2371                         }
2372                         else
2373                                 GL_AlphaToCoverage(false);
2374                 }
2375         }
2376         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2377         {
2378                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2379                 {
2380                         switch(rsurface.texture->offsetmapping)
2381                         {
2382                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2383                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2385                         case OFFSETMAPPING_OFF: break;
2386                         }
2387                 }
2388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2389                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2391                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2392                 // directional model lighting
2393                 mode = SHADERMODE_LIGHTDIRECTION;
2394                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2395                         permutation |= SHADERPERMUTATION_GLOW;
2396                 permutation |= SHADERPERMUTATION_DIFFUSE;
2397                 if (specularscale > 0)
2398                         permutation |= SHADERPERMUTATION_SPECULAR;
2399                 if (r_refdef.fogenabled)
2400                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2401                 if (rsurface.texture->colormapping)
2402                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2403                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2404                 {
2405                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2406                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2407
2408                         if (r_shadow_shadowmap2ddepthbuffer)
2409                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2410                 }
2411                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2412                         permutation |= SHADERPERMUTATION_REFLECTION;
2413                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2414                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2415                 if (rsurface.texture->reflectmasktexture)
2416                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2417                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2418                 {
2419                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2420                         if (r_shadow_bouncegrid_state.directional)
2421                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2422                 }
2423                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2424                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425                 // when using alphatocoverage, we don't need alphakill
2426                 if (vid.allowalphatocoverage)
2427                 {
2428                         if (r_transparent_alphatocoverage.integer)
2429                         {
2430                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2431                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2432                         }
2433                         else
2434                                 GL_AlphaToCoverage(false);
2435                 }
2436         }
2437         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2438         {
2439                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2440                 {
2441                         switch(rsurface.texture->offsetmapping)
2442                         {
2443                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2444                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2445                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2446                         case OFFSETMAPPING_OFF: break;
2447                         }
2448                 }
2449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2450                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2452                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2453                 // ambient model lighting
2454                 mode = SHADERMODE_LIGHTDIRECTION;
2455                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2456                         permutation |= SHADERPERMUTATION_GLOW;
2457                 if (r_refdef.fogenabled)
2458                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2459                 if (rsurface.texture->colormapping)
2460                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2461                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2462                 {
2463                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2464                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2465
2466                         if (r_shadow_shadowmap2ddepthbuffer)
2467                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2468                 }
2469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2470                         permutation |= SHADERPERMUTATION_REFLECTION;
2471                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2472                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2473                 if (rsurface.texture->reflectmasktexture)
2474                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2475                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2476                 {
2477                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2478                         if (r_shadow_bouncegrid_state.directional)
2479                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2480                 }
2481                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2482                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483                 // when using alphatocoverage, we don't need alphakill
2484                 if (vid.allowalphatocoverage)
2485                 {
2486                         if (r_transparent_alphatocoverage.integer)
2487                         {
2488                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2489                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2490                         }
2491                         else
2492                                 GL_AlphaToCoverage(false);
2493                 }
2494         }
2495         else
2496         {
2497                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2498                 {
2499                         switch(rsurface.texture->offsetmapping)
2500                         {
2501                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2502                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2503                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2504                         case OFFSETMAPPING_OFF: break;
2505                         }
2506                 }
2507                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2508                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2509                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2510                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2511                 // lightmapped wall
2512                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2513                         permutation |= SHADERPERMUTATION_GLOW;
2514                 if (r_refdef.fogenabled)
2515                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2516                 if (rsurface.texture->colormapping)
2517                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2518                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2519                 {
2520                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2521                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2522
2523                         if (r_shadow_shadowmap2ddepthbuffer)
2524                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2525                 }
2526                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2527                         permutation |= SHADERPERMUTATION_REFLECTION;
2528                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2529                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2530                 if (rsurface.texture->reflectmasktexture)
2531                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2532                 if (FAKELIGHT_ENABLED)
2533                 {
2534                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2535                         mode = SHADERMODE_FAKELIGHT;
2536                         permutation |= SHADERPERMUTATION_DIFFUSE;
2537                         if (specularscale > 0)
2538                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2539                 }
2540                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2541                 {
2542                         // deluxemapping (light direction texture)
2543                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2544                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2545                         else
2546                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2547                         permutation |= SHADERPERMUTATION_DIFFUSE;
2548                         if (specularscale > 0)
2549                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2550                 }
2551                 else if (r_glsl_deluxemapping.integer >= 2)
2552                 {
2553                         // fake deluxemapping (uniform light direction in tangentspace)
2554                         if (rsurface.uselightmaptexture)
2555                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2556                         else
2557                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2558                         permutation |= SHADERPERMUTATION_DIFFUSE;
2559                         if (specularscale > 0)
2560                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2561                 }
2562                 else if (rsurface.uselightmaptexture)
2563                 {
2564                         // ordinary lightmapping (q1bsp, q3bsp)
2565                         mode = SHADERMODE_LIGHTMAP;
2566                 }
2567                 else
2568                 {
2569                         // ordinary vertex coloring (q3bsp)
2570                         mode = SHADERMODE_VERTEXCOLOR;
2571                 }
2572                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2573                 {
2574                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2575                         if (r_shadow_bouncegrid_state.directional)
2576                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2577                 }
2578                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2579                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2580                 // when using alphatocoverage, we don't need alphakill
2581                 if (vid.allowalphatocoverage)
2582                 {
2583                         if (r_transparent_alphatocoverage.integer)
2584                         {
2585                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2586                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2587                         }
2588                         else
2589                                 GL_AlphaToCoverage(false);
2590                 }
2591         }
2592         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2593                 colormod = dummy_colormod;
2594         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2595                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2596         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2597                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2598         switch(vid.renderpath)
2599         {
2600         case RENDERPATH_D3D9:
2601 #ifdef SUPPORTD3D
2602                 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);
2603                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2604                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2605                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2606                 if (mode == SHADERMODE_LIGHTSOURCE)
2607                 {
2608                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2609                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610                 }
2611                 else
2612                 {
2613                         if (mode == SHADERMODE_LIGHTDIRECTION)
2614                         {
2615                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2616                         }
2617                 }
2618                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2619                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2620                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2621                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2622                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2623
2624                 if (mode == SHADERMODE_LIGHTSOURCE)
2625                 {
2626                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2627                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2628                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2629                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2631
2632                         // additive passes are only darkened by fog, not tinted
2633                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2634                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2635                 }
2636                 else
2637                 {
2638                         if (mode == SHADERMODE_FLATCOLOR)
2639                         {
2640                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2641                         }
2642                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2643                         {
2644                                 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]);
2645                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2646                                 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);
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2648                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2649                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2651                         }
2652                         else
2653                         {
2654                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2656                                 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);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2658                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2659                         }
2660                         // additive passes are only darkened by fog, not tinted
2661                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2662                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2663                         else
2664                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2665                         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);
2666                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2667                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2668                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2669                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2670                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2671                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2672                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2673                         if (mode == SHADERMODE_WATER)
2674                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2675                 }
2676                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2677                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2678                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2679                 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));
2680                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2681                 if (rsurface.texture->pantstexture)
2682                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2683                 else
2684                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2685                 if (rsurface.texture->shirttexture)
2686                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2687                 else
2688                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2689                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2690                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2691                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2692                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2693                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2694                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2695                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2696                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2697                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2698                         );
2699                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2700                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2701                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2702                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2703
2704                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2705                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2706                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2707                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2708                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2709                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2710                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2711                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2712                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2713                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2714                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2715                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2716                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2717                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2718                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2721                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2722                 {
2723                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2724                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2725                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2726                 }
2727                 else
2728                 {
2729                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2730                 }
2731 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2732                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2733                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2734                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2735                 {
2736                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2737                         if (rsurface.rtlight)
2738                         {
2739                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2740                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2741                         }
2742                 }
2743 #endif
2744                 break;
2745         case RENDERPATH_D3D10:
2746                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2747                 break;
2748         case RENDERPATH_D3D11:
2749                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2750                 break;
2751         case RENDERPATH_GL20:
2752         case RENDERPATH_GLES2:
2753                 if (!vid.useinterleavedarrays)
2754                 {
2755                         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);
2756                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2757                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2758                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2759                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2760                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2761                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2762                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2763                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2764                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2765                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2766                 }
2767                 else
2768                 {
2769                         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);
2770                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2771                 }
2772                 // this has to be after RSurf_PrepareVerticesForBatch
2773                 if (rsurface.batchskeletaltransform3x4buffer)
2774                         permutation |= SHADERPERMUTATION_SKELETAL;
2775                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2776 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2777                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2778 #endif
2779                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2780                 if (mode == SHADERMODE_LIGHTSOURCE)
2781                 {
2782                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2783                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2784                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2785                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2786                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2787                         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);
2788         
2789                         // additive passes are only darkened by fog, not tinted
2790                         if (r_glsl_permutation->loc_FogColor >= 0)
2791                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2792                         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);
2793                 }
2794                 else
2795                 {
2796                         if (mode == SHADERMODE_FLATCOLOR)
2797                         {
2798                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2799                         }
2800                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2801                         {
2802                                 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]);
2803                                 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]);
2804                                 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);
2805                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2806                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2807                                 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]);
2808                                 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]);
2809                         }
2810                         else
2811                         {
2812                                 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]);
2813                                 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]);
2814                                 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);
2815                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2816                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2817                         }
2818                         // additive passes are only darkened by fog, not tinted
2819                         if (r_glsl_permutation->loc_FogColor >= 0)
2820                         {
2821                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2822                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2823                                 else
2824                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2825                         }
2826                         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);
2827                         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]);
2828                         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]);
2829                         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]);
2830                         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]);
2831                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2832                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2833                         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);
2834                         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]);
2835                 }
2836                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2837                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2838                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2839                 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]);
2840                 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]);
2841
2842                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2843                 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));
2844                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2845                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2846                 {
2847                         if (rsurface.texture->pantstexture)
2848                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2849                         else
2850                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2851                 }
2852                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2853                 {
2854                         if (rsurface.texture->shirttexture)
2855                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2856                         else
2857                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2858                 }
2859                 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]);
2860                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2861                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2862                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2863                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2864                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2865                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2866                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2867                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2868                         );
2869                 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);
2870                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2871                 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]);
2872                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2873                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2874                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2875
2876                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2877                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2878                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2879                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2880                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2881                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2882                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2883                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2884                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2885                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2886                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2887                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2888                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2889                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2890                 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);
2891                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2892                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2893                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2894                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2895                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2896                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2897                 {
2898                         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);
2899                         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);
2900                         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);
2901                 }
2902                 else
2903                 {
2904                         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);
2905                 }
2906                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2907                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2908                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2909                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2910                 {
2911                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2912                         if (rsurface.rtlight)
2913                         {
2914                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2915                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2916                         }
2917                 }
2918                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2919                 CHECKGLERROR
2920                 break;
2921         case RENDERPATH_GL11:
2922         case RENDERPATH_GL13:
2923         case RENDERPATH_GLES1:
2924                 break;
2925         case RENDERPATH_SOFT:
2926                 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);
2927                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2928                 R_SetupShader_SetPermutationSoft(mode, permutation);
2929                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2930                 if (mode == SHADERMODE_LIGHTSOURCE)
2931                 {
2932                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2933                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2934                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2935                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2936                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2937                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2938         
2939                         // additive passes are only darkened by fog, not tinted
2940                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2941                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2942                 }
2943                 else
2944                 {
2945                         if (mode == SHADERMODE_FLATCOLOR)
2946                         {
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2948                         }
2949                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2950                         {
2951                                 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]);
2952                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2953                                 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);
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2955                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2956                                 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]);
2957                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2958                         }
2959                         else
2960                         {
2961                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2962                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2963                                 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);
2964                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2965                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2966                         }
2967                         // additive passes are only darkened by fog, not tinted
2968                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2969                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2970                         else
2971                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2972                         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);
2973                         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]);
2974                         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]);
2975                         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]);
2976                         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]);
2977                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2978                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2979                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2980                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2981                 }
2982                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2983                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2984                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2985                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2986                 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]);
2987
2988                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2989                 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));
2990                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2991                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2992                 {
2993                         if (rsurface.texture->pantstexture)
2994                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2995                         else
2996                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2997                 }
2998                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2999                 {
3000                         if (rsurface.texture->shirttexture)
3001                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3002                         else
3003                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3004                 }
3005                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3006                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3007                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3008                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3009                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3010                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3011                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3012                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3013                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3014                         );
3015                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3016                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3017                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3018                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3019
3020                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3021                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3022                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3023                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3024                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3025                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3026                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3027                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3028                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3029                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3030                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3031                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3032                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3033                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3034                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3035                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3036                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3037                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3038                 {
3039                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3040                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3041                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3042                 }
3043                 else
3044                 {
3045                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3046                 }
3047 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3048                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3049                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3050                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3051                 {
3052                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3053                         if (rsurface.rtlight)
3054                         {
3055                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3056                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3057                         }
3058                 }
3059                 break;
3060         }
3061 }
3062
3063 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3064 {
3065         // select a permutation of the lighting shader appropriate to this
3066         // combination of texture, entity, light source, and fogging, only use the
3067         // minimum features necessary to avoid wasting rendering time in the
3068         // fragment shader on features that are not being used
3069         unsigned int permutation = 0;
3070         unsigned int mode = 0;
3071         const float *lightcolorbase = rtlight->currentcolor;
3072         float ambientscale = rtlight->ambientscale;
3073         float diffusescale = rtlight->diffusescale;
3074         float specularscale = rtlight->specularscale;
3075         // this is the location of the light in view space
3076         vec3_t viewlightorigin;
3077         // this transforms from view space (camera) to light space (cubemap)
3078         matrix4x4_t viewtolight;
3079         matrix4x4_t lighttoview;
3080         float viewtolight16f[16];
3081         // light source
3082         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3083         if (rtlight->currentcubemap != r_texture_whitecube)
3084                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3085         if (diffusescale > 0)
3086                 permutation |= SHADERPERMUTATION_DIFFUSE;
3087         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3088                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3089         if (r_shadow_usingshadowmap2d)
3090         {
3091                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3092                 if (r_shadow_shadowmapvsdct)
3093                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3094
3095                 if (r_shadow_shadowmap2ddepthbuffer)
3096                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3097         }
3098         if (vid.allowalphatocoverage)
3099                 GL_AlphaToCoverage(false);
3100         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3101         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3102         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3103         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3104         switch(vid.renderpath)
3105         {
3106         case RENDERPATH_D3D9:
3107 #ifdef SUPPORTD3D
3108                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3109                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3110                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3111                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3112                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3113                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3114                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3115                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3116                 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);
3117                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3118                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3119
3120                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3121                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3122                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3123                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3124                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3125 #endif
3126                 break;
3127         case RENDERPATH_D3D10:
3128                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3129                 break;
3130         case RENDERPATH_D3D11:
3131                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3132                 break;
3133         case RENDERPATH_GL20:
3134         case RENDERPATH_GLES2:
3135                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3136                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3137                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3138                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3139                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3140                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3141                 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]);
3142                 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]);
3143                 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);
3144                 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]);
3145                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3146
3147                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3148                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3149                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3150                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3151                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3152                 break;
3153         case RENDERPATH_GL11:
3154         case RENDERPATH_GL13:
3155         case RENDERPATH_GLES1:
3156                 break;
3157         case RENDERPATH_SOFT:
3158                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3159                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3160                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3161                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3162                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3163                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3164                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3165                 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]);
3166                 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);
3167                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3168                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3169
3170                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3171                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3172                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3173                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3174                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3175                 break;
3176         }
3177 }
3178
3179 #define SKINFRAME_HASH 1024
3180
3181 typedef struct
3182 {
3183         unsigned int loadsequence; // incremented each level change
3184         memexpandablearray_t array;
3185         skinframe_t *hash[SKINFRAME_HASH];
3186 }
3187 r_skinframe_t;
3188 r_skinframe_t r_skinframe;
3189
3190 void R_SkinFrame_PrepareForPurge(void)
3191 {
3192         r_skinframe.loadsequence++;
3193         // wrap it without hitting zero
3194         if (r_skinframe.loadsequence >= 200)
3195                 r_skinframe.loadsequence = 1;
3196 }
3197
3198 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3199 {
3200         if (!skinframe)
3201                 return;
3202         // mark the skinframe as used for the purging code
3203         skinframe->loadsequence = r_skinframe.loadsequence;
3204 }
3205
3206 void R_SkinFrame_Purge(void)
3207 {
3208         int i;
3209         skinframe_t *s;
3210         for (i = 0;i < SKINFRAME_HASH;i++)
3211         {
3212                 for (s = r_skinframe.hash[i];s;s = s->next)
3213                 {
3214                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3215                         {
3216                                 if (s->merged == s->base)
3217                                         s->merged = NULL;
3218                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3219                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3220                                 R_PurgeTexture(s->merged);s->merged = NULL;
3221                                 R_PurgeTexture(s->base  );s->base   = NULL;
3222                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3223                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3224                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3225                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3226                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3227                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3228                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3229                                 s->loadsequence = 0;
3230                         }
3231                 }
3232         }
3233 }
3234
3235 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3236         skinframe_t *item;
3237         char basename[MAX_QPATH];
3238
3239         Image_StripImageExtension(name, basename, sizeof(basename));
3240
3241         if( last == NULL ) {
3242                 int hashindex;
3243                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3244                 item = r_skinframe.hash[hashindex];
3245         } else {
3246                 item = last->next;
3247         }
3248
3249         // linearly search through the hash bucket
3250         for( ; item ; item = item->next ) {
3251                 if( !strcmp( item->basename, basename ) ) {
3252                         return item;
3253                 }
3254         }
3255         return NULL;
3256 }
3257
3258 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3259 {
3260         skinframe_t *item;
3261         int hashindex;
3262         char basename[MAX_QPATH];
3263
3264         Image_StripImageExtension(name, basename, sizeof(basename));
3265
3266         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3267         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3268                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3269                         break;
3270
3271         if (!item) {
3272                 rtexture_t *dyntexture;
3273                 // check whether its a dynamic texture
3274                 dyntexture = CL_GetDynTexture( basename );
3275                 if (!add && !dyntexture)
3276                         return NULL;
3277                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3278                 memset(item, 0, sizeof(*item));
3279                 strlcpy(item->basename, basename, sizeof(item->basename));
3280                 item->base = dyntexture; // either NULL or dyntexture handle
3281                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3282                 item->comparewidth = comparewidth;
3283                 item->compareheight = compareheight;
3284                 item->comparecrc = comparecrc;
3285                 item->next = r_skinframe.hash[hashindex];
3286                 r_skinframe.hash[hashindex] = item;
3287         }
3288         else if (textureflags & TEXF_FORCE_RELOAD)
3289         {
3290                 rtexture_t *dyntexture;
3291                 // check whether its a dynamic texture
3292                 dyntexture = CL_GetDynTexture( basename );
3293                 if (!add && !dyntexture)
3294                         return NULL;
3295                 if (item->merged == item->base)
3296                         item->merged = NULL;
3297                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3298                 R_PurgeTexture(item->stain );item->stain  = NULL;
3299                 R_PurgeTexture(item->merged);item->merged = NULL;
3300                 R_PurgeTexture(item->base  );item->base   = NULL;
3301                 R_PurgeTexture(item->pants );item->pants  = NULL;
3302                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3303                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3304                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3305                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3306                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3307         R_PurgeTexture(item->reflect);item->reflect = NULL;
3308                 item->loadsequence = 0;
3309         }
3310         else if( item->base == NULL )
3311         {
3312                 rtexture_t *dyntexture;
3313                 // check whether its a dynamic texture
3314                 // 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]
3315                 dyntexture = CL_GetDynTexture( basename );
3316                 item->base = dyntexture; // either NULL or dyntexture handle
3317         }
3318
3319         R_SkinFrame_MarkUsed(item);
3320         return item;
3321 }
3322
3323 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3324         { \
3325                 unsigned long long avgcolor[5], wsum; \
3326                 int pix, comp, w; \
3327                 avgcolor[0] = 0; \
3328                 avgcolor[1] = 0; \
3329                 avgcolor[2] = 0; \
3330                 avgcolor[3] = 0; \
3331                 avgcolor[4] = 0; \
3332                 wsum = 0; \
3333                 for(pix = 0; pix < cnt; ++pix) \
3334                 { \
3335                         w = 0; \
3336                         for(comp = 0; comp < 3; ++comp) \
3337                                 w += getpixel; \
3338                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3339                         { \
3340                                 ++wsum; \
3341                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3342                                 w = getpixel; \
3343                                 for(comp = 0; comp < 3; ++comp) \
3344                                         avgcolor[comp] += getpixel * w; \
3345                                 avgcolor[3] += w; \
3346                         } \
3347                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3348                         avgcolor[4] += getpixel; \
3349                 } \
3350                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3351                         avgcolor[3] = 1; \
3352                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3353                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3354                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3355                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3356         }
3357
3358 extern cvar_t gl_picmip;
3359 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3360 {
3361         int j;
3362         unsigned char *pixels;
3363         unsigned char *bumppixels;
3364         unsigned char *basepixels = NULL;
3365         int basepixels_width = 0;
3366         int basepixels_height = 0;
3367         skinframe_t *skinframe;
3368         rtexture_t *ddsbase = NULL;
3369         qboolean ddshasalpha = false;
3370         float ddsavgcolor[4];
3371         char basename[MAX_QPATH];
3372         int miplevel = R_PicmipForFlags(textureflags);
3373         int savemiplevel = miplevel;
3374         int mymiplevel;
3375         char vabuf[1024];
3376
3377         if (cls.state == ca_dedicated)
3378                 return NULL;
3379
3380         // return an existing skinframe if already loaded
3381         // if loading of the first image fails, don't make a new skinframe as it
3382         // would cause all future lookups of this to be missing
3383         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3384         if (skinframe && skinframe->base)
3385                 return skinframe;
3386
3387         Image_StripImageExtension(name, basename, sizeof(basename));
3388
3389         // check for DDS texture file first
3390         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3391         {
3392                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3393                 if (basepixels == NULL)
3394                         return NULL;
3395         }
3396
3397         // FIXME handle miplevel
3398
3399         if (developer_loading.integer)
3400                 Con_Printf("loading skin \"%s\"\n", name);
3401
3402         // we've got some pixels to store, so really allocate this new texture now
3403         if (!skinframe)
3404                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3405         textureflags &= ~TEXF_FORCE_RELOAD;
3406         skinframe->stain = NULL;
3407         skinframe->merged = NULL;
3408         skinframe->base = NULL;
3409         skinframe->pants = NULL;
3410         skinframe->shirt = NULL;
3411         skinframe->nmap = NULL;
3412         skinframe->gloss = NULL;
3413         skinframe->glow = NULL;
3414         skinframe->fog = NULL;
3415         skinframe->reflect = NULL;
3416         skinframe->hasalpha = false;
3417         // we could store the q2animname here too
3418
3419         if (ddsbase)
3420         {
3421                 skinframe->base = ddsbase;
3422                 skinframe->hasalpha = ddshasalpha;
3423                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3424                 if (r_loadfog && skinframe->hasalpha)
3425                         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);
3426                 //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]);
3427         }
3428         else
3429         {
3430                 basepixels_width = image_width;
3431                 basepixels_height = image_height;
3432                 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);
3433                 if (textureflags & TEXF_ALPHA)
3434                 {
3435                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3436                         {
3437                                 if (basepixels[j] < 255)
3438                                 {
3439                                         skinframe->hasalpha = true;
3440                                         break;
3441                                 }
3442                         }
3443                         if (r_loadfog && skinframe->hasalpha)
3444                         {
3445                                 // has transparent pixels
3446                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3447                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3448                                 {
3449                                         pixels[j+0] = 255;
3450                                         pixels[j+1] = 255;
3451                                         pixels[j+2] = 255;
3452                                         pixels[j+3] = basepixels[j+3];
3453                                 }
3454                                 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);
3455                                 Mem_Free(pixels);
3456                         }
3457                 }
3458                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3459 #ifndef USE_GLES2
3460                 //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]);
3461                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3462                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3463                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3464                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3465 #endif
3466         }
3467
3468         if (r_loaddds)
3469         {
3470                 mymiplevel = savemiplevel;
3471                 if (r_loadnormalmap)
3472                         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);
3473                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3474                 if (r_loadgloss)
3475                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3476                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3477                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3478                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3479         }
3480
3481         // _norm is the name used by tenebrae and has been adopted as standard
3482         if (r_loadnormalmap && skinframe->nmap == NULL)
3483         {
3484                 mymiplevel = savemiplevel;
3485                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3486                 {
3487                         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);
3488                         Mem_Free(pixels);
3489                         pixels = NULL;
3490                 }
3491                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3492                 {
3493                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3494                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3495                         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);
3496                         Mem_Free(pixels);
3497                         Mem_Free(bumppixels);
3498                 }
3499                 else if (r_shadow_bumpscale_basetexture.value > 0)
3500                 {
3501                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3502                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3503                         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);
3504                         Mem_Free(pixels);
3505                 }
3506 #ifndef USE_GLES2
3507                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3508                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3509 #endif
3510         }
3511
3512         // _luma is supported only for tenebrae compatibility
3513         // _glow is the preferred name
3514         mymiplevel = savemiplevel;
3515         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))))
3516         {
3517                 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);
3518 #ifndef USE_GLES2
3519                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3520                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3521 #endif
3522                 Mem_Free(pixels);pixels = NULL;
3523         }
3524
3525         mymiplevel = savemiplevel;
3526         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3527         {
3528                 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);
3529 #ifndef USE_GLES2
3530                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3531                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3532 #endif
3533                 Mem_Free(pixels);
3534                 pixels = NULL;
3535         }
3536
3537         mymiplevel = savemiplevel;
3538         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3539         {
3540                 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);
3541 #ifndef USE_GLES2
3542                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3543                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3544 #endif
3545                 Mem_Free(pixels);
3546                 pixels = NULL;
3547         }
3548
3549         mymiplevel = savemiplevel;
3550         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3551         {
3552                 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);
3553 #ifndef USE_GLES2
3554                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3555                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3556 #endif
3557                 Mem_Free(pixels);
3558                 pixels = NULL;
3559         }
3560
3561         mymiplevel = savemiplevel;
3562         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3563         {
3564                 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);
3565 #ifndef USE_GLES2
3566                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3567                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3568 #endif
3569                 Mem_Free(pixels);
3570                 pixels = NULL;
3571         }
3572
3573         if (basepixels)
3574                 Mem_Free(basepixels);
3575
3576         return skinframe;
3577 }
3578
3579 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3580 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3581 {
3582         int i;
3583         skinframe_t *skinframe;
3584         char vabuf[1024];
3585
3586         if (cls.state == ca_dedicated)
3587                 return NULL;
3588
3589         // if already loaded just return it, otherwise make a new skinframe
3590         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3591         if (skinframe->base)
3592                 return skinframe;
3593         textureflags &= ~TEXF_FORCE_RELOAD;
3594
3595         skinframe->stain = NULL;
3596         skinframe->merged = NULL;
3597         skinframe->base = NULL;
3598         skinframe->pants = NULL;
3599         skinframe->shirt = NULL;
3600         skinframe->nmap = NULL;
3601         skinframe->gloss = NULL;
3602         skinframe->glow = NULL;
3603         skinframe->fog = NULL;
3604         skinframe->reflect = NULL;
3605         skinframe->hasalpha = false;
3606
3607         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3608         if (!skindata)
3609                 return NULL;
3610
3611         if (developer_loading.integer)
3612                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3613
3614         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3615         {
3616                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3617                 unsigned char *b = a + width * height * 4;
3618                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3619                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3620                 Mem_Free(a);
3621         }
3622         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3623         if (textureflags & TEXF_ALPHA)
3624         {
3625                 for (i = 3;i < width * height * 4;i += 4)
3626                 {
3627                         if (skindata[i] < 255)
3628                         {
3629                                 skinframe->hasalpha = true;
3630                                 break;
3631                         }
3632                 }
3633                 if (r_loadfog && skinframe->hasalpha)
3634                 {
3635                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3636                         memcpy(fogpixels, skindata, width * height * 4);
3637                         for (i = 0;i < width * height * 4;i += 4)
3638                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3639                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3640                         Mem_Free(fogpixels);
3641                 }
3642         }
3643
3644         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3645         //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]);
3646
3647         return skinframe;
3648 }
3649
3650 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3651 {
3652         int i;
3653         int featuresmask;
3654         skinframe_t *skinframe;
3655
3656         if (cls.state == ca_dedicated)
3657                 return NULL;
3658
3659         // if already loaded just return it, otherwise make a new skinframe
3660         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3661         if (skinframe->base)
3662                 return skinframe;
3663         //textureflags &= ~TEXF_FORCE_RELOAD;
3664
3665         skinframe->stain = NULL;
3666         skinframe->merged = NULL;
3667         skinframe->base = NULL;
3668         skinframe->pants = NULL;
3669         skinframe->shirt = NULL;
3670         skinframe->nmap = NULL;
3671         skinframe->gloss = NULL;
3672         skinframe->glow = NULL;
3673         skinframe->fog = NULL;
3674         skinframe->reflect = NULL;
3675         skinframe->hasalpha = false;
3676
3677         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3678         if (!skindata)
3679                 return NULL;
3680
3681         if (developer_loading.integer)
3682                 Con_Printf("loading quake skin \"%s\"\n", name);
3683
3684         // 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)
3685         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3686         memcpy(skinframe->qpixels, skindata, width*height);
3687         skinframe->qwidth = width;
3688         skinframe->qheight = height;
3689
3690         featuresmask = 0;
3691         for (i = 0;i < width * height;i++)
3692                 featuresmask |= palette_featureflags[skindata[i]];
3693
3694         skinframe->hasalpha = false;
3695         // fence textures
3696         if (name[0] == '{')
3697                 skinframe->hasalpha = true;
3698         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3699         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3700         skinframe->qgeneratemerged = true;
3701         skinframe->qgeneratebase = skinframe->qhascolormapping;
3702         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3703
3704         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3705         //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]);
3706
3707         return skinframe;
3708 }
3709
3710 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3711 {
3712         int width;
3713         int height;
3714         unsigned char *skindata;
3715         char vabuf[1024];
3716
3717         if (!skinframe->qpixels)
3718                 return;
3719
3720         if (!skinframe->qhascolormapping)
3721                 colormapped = false;
3722
3723         if (colormapped)
3724         {
3725                 if (!skinframe->qgeneratebase)
3726                         return;
3727         }
3728         else
3729         {
3730                 if (!skinframe->qgeneratemerged)
3731                         return;
3732         }
3733
3734         width = skinframe->qwidth;
3735         height = skinframe->qheight;
3736         skindata = skinframe->qpixels;
3737
3738         if (skinframe->qgeneratenmap)
3739         {
3740                 unsigned char *a, *b;
3741                 skinframe->qgeneratenmap = false;
3742                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3743                 b = a + width * height * 4;
3744                 // use either a custom palette or the quake palette
3745                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3746                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3747                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3748                 Mem_Free(a);
3749         }
3750
3751         if (skinframe->qgenerateglow)
3752         {
3753                 skinframe->qgenerateglow = false;
3754                 if (skinframe->hasalpha) // fence textures
3755                         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 | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3756                 else
3757                         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
3758         }
3759
3760         if (colormapped)
3761         {
3762                 skinframe->qgeneratebase = false;
3763                 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);
3764                 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);
3765                 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);
3766         }
3767         else
3768         {
3769                 skinframe->qgeneratemerged = false;
3770                 if (skinframe->hasalpha) // fence textures
3771                         skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3772                 else
3773                         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);
3774         }
3775
3776         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3777         {
3778                 Mem_Free(skinframe->qpixels);
3779                 skinframe->qpixels = NULL;
3780         }
3781 }
3782
3783 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)
3784 {
3785         int i;
3786         skinframe_t *skinframe;
3787         char vabuf[1024];
3788
3789         if (cls.state == ca_dedicated)
3790                 return NULL;
3791
3792         // if already loaded just return it, otherwise make a new skinframe
3793         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3794         if (skinframe->base)
3795                 return skinframe;
3796         textureflags &= ~TEXF_FORCE_RELOAD;
3797
3798         skinframe->stain = NULL;
3799         skinframe->merged = NULL;
3800         skinframe->base = NULL;
3801         skinframe->pants = NULL;
3802         skinframe->shirt = NULL;
3803         skinframe->nmap = NULL;
3804         skinframe->gloss = NULL;
3805         skinframe->glow = NULL;
3806         skinframe->fog = NULL;
3807         skinframe->reflect = NULL;
3808         skinframe->hasalpha = false;
3809
3810         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3811         if (!skindata)
3812                 return NULL;
3813
3814         if (developer_loading.integer)
3815                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3816
3817         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3818         if (textureflags & TEXF_ALPHA)
3819         {
3820                 for (i = 0;i < width * height;i++)
3821                 {
3822                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3823                         {
3824                                 skinframe->hasalpha = true;
3825                                 break;
3826                         }
3827                 }
3828                 if (r_loadfog && skinframe->hasalpha)
3829                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3830         }
3831
3832         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3833         //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]);
3834
3835         return skinframe;
3836 }
3837
3838 skinframe_t *R_SkinFrame_LoadMissing(void)
3839 {
3840         skinframe_t *skinframe;
3841
3842         if (cls.state == ca_dedicated)
3843                 return NULL;
3844
3845         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3846         skinframe->stain = NULL;
3847         skinframe->merged = NULL;
3848         skinframe->base = NULL;
3849         skinframe->pants = NULL;
3850         skinframe->shirt = NULL;
3851         skinframe->nmap = NULL;
3852         skinframe->gloss = NULL;
3853         skinframe->glow = NULL;
3854         skinframe->fog = NULL;
3855         skinframe->reflect = NULL;
3856         skinframe->hasalpha = false;
3857
3858         skinframe->avgcolor[0] = rand() / RAND_MAX;
3859         skinframe->avgcolor[1] = rand() / RAND_MAX;
3860         skinframe->avgcolor[2] = rand() / RAND_MAX;
3861         skinframe->avgcolor[3] = 1;
3862
3863         return skinframe;
3864 }
3865
3866 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3867 typedef struct suffixinfo_s
3868 {
3869         const char *suffix;
3870         qboolean flipx, flipy, flipdiagonal;
3871 }
3872 suffixinfo_t;
3873 static suffixinfo_t suffix[3][6] =
3874 {
3875         {
3876                 {"px",   false, false, false},
3877                 {"nx",   false, false, false},
3878                 {"py",   false, false, false},
3879                 {"ny",   false, false, false},
3880                 {"pz",   false, false, false},
3881                 {"nz",   false, false, false}
3882         },
3883         {
3884                 {"posx", false, false, false},
3885                 {"negx", false, false, false},
3886                 {"posy", false, false, false},
3887                 {"negy", false, false, false},
3888                 {"posz", false, false, false},
3889                 {"negz", false, false, false}
3890         },
3891         {
3892                 {"rt",    true, false,  true},
3893                 {"lf",   false,  true,  true},
3894                 {"ft",    true,  true, false},
3895                 {"bk",   false, false, false},
3896                 {"up",    true, false,  true},
3897                 {"dn",    true, false,  true}
3898         }
3899 };
3900
3901 static int componentorder[4] = {0, 1, 2, 3};
3902
3903 static rtexture_t *R_LoadCubemap(const char *basename)
3904 {
3905         int i, j, cubemapsize;
3906         unsigned char *cubemappixels, *image_buffer;
3907         rtexture_t *cubemaptexture;
3908         char name[256];
3909         // must start 0 so the first loadimagepixels has no requested width/height
3910         cubemapsize = 0;
3911         cubemappixels = NULL;
3912         cubemaptexture = NULL;
3913         // keep trying different suffix groups (posx, px, rt) until one loads
3914         for (j = 0;j < 3 && !cubemappixels;j++)
3915         {
3916                 // load the 6 images in the suffix group
3917                 for (i = 0;i < 6;i++)
3918                 {
3919                         // generate an image name based on the base and and suffix
3920                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3921                         // load it
3922                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3923                         {
3924                                 // an image loaded, make sure width and height are equal
3925                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3926                                 {
3927                                         // if this is the first image to load successfully, allocate the cubemap memory
3928                                         if (!cubemappixels && image_width >= 1)
3929                                         {
3930                                                 cubemapsize = image_width;
3931                                                 // note this clears to black, so unavailable sides are black
3932                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3933                                         }
3934                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3935                                         if (cubemappixels)
3936                                                 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);
3937                                 }
3938                                 else
3939                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3940                                 // free the image
3941                                 Mem_Free(image_buffer);
3942                         }
3943                 }
3944         }
3945         // if a cubemap loaded, upload it
3946         if (cubemappixels)
3947         {
3948                 if (developer_loading.integer)
3949                         Con_Printf("loading cubemap \"%s\"\n", basename);
3950
3951                 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);
3952                 Mem_Free(cubemappixels);
3953         }
3954         else
3955         {
3956                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3957                 if (developer_loading.integer)
3958                 {
3959                         Con_Printf("(tried tried images ");
3960                         for (j = 0;j < 3;j++)
3961                                 for (i = 0;i < 6;i++)
3962                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3963                         Con_Print(" and was unable to find any of them).\n");
3964                 }
3965         }
3966         return cubemaptexture;
3967 }
3968
3969 rtexture_t *R_GetCubemap(const char *basename)
3970 {
3971         int i;
3972         for (i = 0;i < r_texture_numcubemaps;i++)
3973                 if (r_texture_cubemaps[i] != NULL)
3974                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3975                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3976         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3977                 return r_texture_whitecube;
3978         r_texture_numcubemaps++;
3979         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3980         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3981         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3982         return r_texture_cubemaps[i]->texture;
3983 }
3984
3985 static void R_Main_FreeViewCache(void)
3986 {
3987         if (r_refdef.viewcache.entityvisible)
3988                 Mem_Free(r_refdef.viewcache.entityvisible);
3989         if (r_refdef.viewcache.world_pvsbits)
3990                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3991         if (r_refdef.viewcache.world_leafvisible)
3992                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3993         if (r_refdef.viewcache.world_surfacevisible)
3994                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3995         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3996 }
3997
3998 static void R_Main_ResizeViewCache(void)
3999 {
4000         int numentities = r_refdef.scene.numentities;
4001         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4002         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4003         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4004         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4005         if (r_refdef.viewcache.maxentities < numentities)
4006         {
4007                 r_refdef.viewcache.maxentities = numentities;
4008                 if (r_refdef.viewcache.entityvisible)
4009                         Mem_Free(r_refdef.viewcache.entityvisible);
4010                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4011         }
4012         if (r_refdef.viewcache.world_numclusters != numclusters)
4013         {
4014                 r_refdef.viewcache.world_numclusters = numclusters;
4015                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4016                 if (r_refdef.viewcache.world_pvsbits)
4017                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4018                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4019         }
4020         if (r_refdef.viewcache.world_numleafs != numleafs)
4021         {
4022                 r_refdef.viewcache.world_numleafs = numleafs;
4023                 if (r_refdef.viewcache.world_leafvisible)
4024                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4025                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4026         }
4027         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4028         {
4029                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4030                 if (r_refdef.viewcache.world_surfacevisible)
4031                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4032                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4033         }
4034 }
4035
4036 extern rtexture_t *loadingscreentexture;
4037 static void gl_main_start(void)
4038 {
4039         loadingscreentexture = NULL;
4040         r_texture_blanknormalmap = NULL;
4041         r_texture_white = NULL;
4042         r_texture_grey128 = NULL;
4043         r_texture_black = NULL;
4044         r_texture_whitecube = NULL;
4045         r_texture_normalizationcube = NULL;
4046         r_texture_fogattenuation = NULL;
4047         r_texture_fogheighttexture = NULL;
4048         r_texture_gammaramps = NULL;
4049         r_texture_numcubemaps = 0;
4050         r_uniformbufferalignment = 32;
4051
4052         r_loaddds = r_texture_dds_load.integer != 0;
4053         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4054
4055         switch(vid.renderpath)
4056         {
4057         case RENDERPATH_GL20:
4058         case RENDERPATH_D3D9:
4059         case RENDERPATH_D3D10:
4060         case RENDERPATH_D3D11:
4061         case RENDERPATH_SOFT:
4062         case RENDERPATH_GLES2:
4063                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4064                 Cvar_SetValueQuick(&gl_combine, 1);
4065                 Cvar_SetValueQuick(&r_glsl, 1);
4066                 r_loadnormalmap = true;
4067                 r_loadgloss = true;
4068                 r_loadfog = false;
4069 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4070                 if (vid.support.arb_uniform_buffer_object)
4071                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4072 #endif
4073                         break;
4074         case RENDERPATH_GL13:
4075         case RENDERPATH_GLES1:
4076                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4077                 Cvar_SetValueQuick(&gl_combine, 1);
4078                 Cvar_SetValueQuick(&r_glsl, 0);
4079                 r_loadnormalmap = false;
4080                 r_loadgloss = false;
4081                 r_loadfog = true;
4082                 break;
4083         case RENDERPATH_GL11:
4084                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4085                 Cvar_SetValueQuick(&gl_combine, 0);
4086                 Cvar_SetValueQuick(&r_glsl, 0);
4087                 r_loadnormalmap = false;
4088                 r_loadgloss = false;
4089                 r_loadfog = true;
4090                 break;
4091         }
4092
4093         R_AnimCache_Free();
4094         R_FrameData_Reset();
4095         R_BufferData_Reset();
4096
4097         r_numqueries = 0;
4098         r_maxqueries = 0;
4099         memset(r_queries, 0, sizeof(r_queries));
4100
4101         r_qwskincache = NULL;
4102         r_qwskincache_size = 0;
4103
4104         // due to caching of texture_t references, the collision cache must be reset
4105         Collision_Cache_Reset(true);
4106
4107         // set up r_skinframe loading system for textures
4108         memset(&r_skinframe, 0, sizeof(r_skinframe));
4109         r_skinframe.loadsequence = 1;
4110         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4111
4112         r_main_texturepool = R_AllocTexturePool();
4113         R_BuildBlankTextures();
4114         R_BuildNoTexture();
4115         if (vid.support.arb_texture_cube_map)
4116         {
4117                 R_BuildWhiteCube();
4118                 R_BuildNormalizationCube();
4119         }
4120         r_texture_fogattenuation = NULL;
4121         r_texture_fogheighttexture = NULL;
4122         r_texture_gammaramps = NULL;
4123         //r_texture_fogintensity = NULL;
4124         memset(&r_fb, 0, sizeof(r_fb));
4125         r_glsl_permutation = NULL;
4126         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4127         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4128         glslshaderstring = NULL;
4129 #ifdef SUPPORTD3D
4130         r_hlsl_permutation = NULL;
4131         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4132         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4133 #endif
4134         hlslshaderstring = NULL;
4135         memset(&r_svbsp, 0, sizeof (r_svbsp));
4136
4137         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4138         r_texture_numcubemaps = 0;
4139
4140         r_refdef.fogmasktable_density = 0;
4141
4142 #ifdef __ANDROID__
4143         // For Steelstorm Android
4144         // FIXME CACHE the program and reload
4145         // FIXME see possible combinations for SS:BR android
4146         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4147         R_SetupShader_SetPermutationGLSL(0, 12);
4148         R_SetupShader_SetPermutationGLSL(0, 13);
4149         R_SetupShader_SetPermutationGLSL(0, 8388621);
4150         R_SetupShader_SetPermutationGLSL(3, 0);
4151         R_SetupShader_SetPermutationGLSL(3, 2048);
4152         R_SetupShader_SetPermutationGLSL(5, 0);
4153         R_SetupShader_SetPermutationGLSL(5, 2);
4154         R_SetupShader_SetPermutationGLSL(5, 2048);
4155         R_SetupShader_SetPermutationGLSL(5, 8388608);
4156         R_SetupShader_SetPermutationGLSL(11, 1);
4157         R_SetupShader_SetPermutationGLSL(11, 2049);
4158         R_SetupShader_SetPermutationGLSL(11, 8193);
4159         R_SetupShader_SetPermutationGLSL(11, 10241);
4160         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4161 #endif
4162 }
4163
4164 static void gl_main_shutdown(void)
4165 {
4166         R_AnimCache_Free();
4167         R_FrameData_Reset();
4168         R_BufferData_Reset();
4169
4170         R_Main_FreeViewCache();
4171
4172         switch(vid.renderpath)
4173         {
4174         case RENDERPATH_GL11:
4175         case RENDERPATH_GL13:
4176         case RENDERPATH_GL20:
4177         case RENDERPATH_GLES1:
4178         case RENDERPATH_GLES2:
4179 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4180                 if (r_maxqueries)
4181                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4182 #endif
4183                 break;
4184         case RENDERPATH_D3D9:
4185                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4186                 break;
4187         case RENDERPATH_D3D10:
4188                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4189                 break;
4190         case RENDERPATH_D3D11:
4191                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4192                 break;
4193         case RENDERPATH_SOFT:
4194                 break;
4195         }
4196
4197         r_numqueries = 0;
4198         r_maxqueries = 0;
4199         memset(r_queries, 0, sizeof(r_queries));
4200
4201         r_qwskincache = NULL;
4202         r_qwskincache_size = 0;
4203
4204         // clear out the r_skinframe state
4205         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4206         memset(&r_skinframe, 0, sizeof(r_skinframe));
4207
4208         if (r_svbsp.nodes)
4209                 Mem_Free(r_svbsp.nodes);
4210         memset(&r_svbsp, 0, sizeof (r_svbsp));
4211         R_FreeTexturePool(&r_main_texturepool);
4212         loadingscreentexture = NULL;
4213         r_texture_blanknormalmap = NULL;
4214         r_texture_white = NULL;
4215         r_texture_grey128 = NULL;
4216         r_texture_black = NULL;
4217         r_texture_whitecube = NULL;
4218         r_texture_normalizationcube = NULL;
4219         r_texture_fogattenuation = NULL;
4220         r_texture_fogheighttexture = NULL;
4221         r_texture_gammaramps = NULL;
4222         r_texture_numcubemaps = 0;
4223         //r_texture_fogintensity = NULL;
4224         memset(&r_fb, 0, sizeof(r_fb));
4225         R_GLSL_Restart_f();
4226
4227         r_glsl_permutation = NULL;
4228         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4229         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4230         glslshaderstring = NULL;
4231 #ifdef SUPPORTD3D
4232         r_hlsl_permutation = NULL;
4233         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4234         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4235 #endif
4236         hlslshaderstring = NULL;
4237 }
4238
4239 static void gl_main_newmap(void)
4240 {
4241         // FIXME: move this code to client
4242         char *entities, entname[MAX_QPATH];
4243         if (r_qwskincache)
4244                 Mem_Free(r_qwskincache);
4245         r_qwskincache = NULL;
4246         r_qwskincache_size = 0;
4247         if (cl.worldmodel)
4248         {
4249                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4250                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4251                 {
4252                         CL_ParseEntityLump(entities);
4253                         Mem_Free(entities);
4254                         return;
4255                 }
4256                 if (cl.worldmodel->brush.entities)
4257                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4258         }
4259         R_Main_FreeViewCache();
4260
4261         R_FrameData_Reset();
4262         R_BufferData_Reset();
4263 }
4264
4265 void GL_Main_Init(void)
4266 {
4267         int i;
4268         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4269
4270         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4271         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4272         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4273         if (gamemode == GAME_NEHAHRA)
4274         {
4275                 Cvar_RegisterVariable (&gl_fogenable);
4276                 Cvar_RegisterVariable (&gl_fogdensity);
4277                 Cvar_RegisterVariable (&gl_fogred);
4278                 Cvar_RegisterVariable (&gl_foggreen);
4279                 Cvar_RegisterVariable (&gl_fogblue);
4280                 Cvar_RegisterVariable (&gl_fogstart);
4281                 Cvar_RegisterVariable (&gl_fogend);
4282                 Cvar_RegisterVariable (&gl_skyclip);
4283         }
4284         Cvar_RegisterVariable(&r_motionblur);
4285         Cvar_RegisterVariable(&r_damageblur);
4286         Cvar_RegisterVariable(&r_motionblur_averaging);
4287         Cvar_RegisterVariable(&r_motionblur_randomize);
4288         Cvar_RegisterVariable(&r_motionblur_minblur);
4289         Cvar_RegisterVariable(&r_motionblur_maxblur);
4290         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4291         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4292         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4293         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4294         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4295         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4296         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4297         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4298         Cvar_RegisterVariable(&r_equalize_entities_by);
4299         Cvar_RegisterVariable(&r_equalize_entities_to);
4300         Cvar_RegisterVariable(&r_depthfirst);
4301         Cvar_RegisterVariable(&r_useinfinitefarclip);
4302         Cvar_RegisterVariable(&r_farclip_base);
4303         Cvar_RegisterVariable(&r_farclip_world);
4304         Cvar_RegisterVariable(&r_nearclip);
4305         Cvar_RegisterVariable(&r_deformvertexes);
4306         Cvar_RegisterVariable(&r_transparent);
4307         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4308         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4309         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4310         Cvar_RegisterVariable(&r_showoverdraw);
4311         Cvar_RegisterVariable(&r_showbboxes);
4312         Cvar_RegisterVariable(&r_showsurfaces);
4313         Cvar_RegisterVariable(&r_showtris);
4314         Cvar_RegisterVariable(&r_shownormals);
4315         Cvar_RegisterVariable(&r_showlighting);
4316         Cvar_RegisterVariable(&r_showshadowvolumes);
4317         Cvar_RegisterVariable(&r_showcollisionbrushes);
4318         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4319         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4320         Cvar_RegisterVariable(&r_showdisabledepthtest);
4321         Cvar_RegisterVariable(&r_drawportals);
4322         Cvar_RegisterVariable(&r_drawentities);
4323         Cvar_RegisterVariable(&r_draw2d);
4324         Cvar_RegisterVariable(&r_drawworld);
4325         Cvar_RegisterVariable(&r_cullentities_trace);
4326         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4327         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4328         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4329         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4330         Cvar_RegisterVariable(&r_sortentities);
4331         Cvar_RegisterVariable(&r_drawviewmodel);
4332         Cvar_RegisterVariable(&r_drawexteriormodel);
4333         Cvar_RegisterVariable(&r_speeds);
4334         Cvar_RegisterVariable(&r_fullbrights);
4335         Cvar_RegisterVariable(&r_wateralpha);
4336         Cvar_RegisterVariable(&r_dynamic);
4337         Cvar_RegisterVariable(&r_fakelight);
4338         Cvar_RegisterVariable(&r_fakelight_intensity);
4339         Cvar_RegisterVariable(&r_fullbright);
4340         Cvar_RegisterVariable(&r_shadows);
4341         Cvar_RegisterVariable(&r_shadows_darken);
4342         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4343         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4344         Cvar_RegisterVariable(&r_shadows_throwdistance);
4345         Cvar_RegisterVariable(&r_shadows_throwdirection);
4346         Cvar_RegisterVariable(&r_shadows_focus);
4347         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4348         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4349         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4350         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4351         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4352         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4353         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4354         Cvar_RegisterVariable(&r_fog_exp2);
4355         Cvar_RegisterVariable(&r_fog_clear);
4356         Cvar_RegisterVariable(&r_drawfog);
4357         Cvar_RegisterVariable(&r_transparentdepthmasking);
4358         Cvar_RegisterVariable(&r_transparent_sortmindist);
4359         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4360         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4361         Cvar_RegisterVariable(&r_texture_dds_load);
4362         Cvar_RegisterVariable(&r_texture_dds_save);
4363         Cvar_RegisterVariable(&r_textureunits);
4364         Cvar_RegisterVariable(&gl_combine);
4365         Cvar_RegisterVariable(&r_usedepthtextures);
4366         Cvar_RegisterVariable(&r_viewfbo);
4367         Cvar_RegisterVariable(&r_viewscale);
4368         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4369         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4370         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4371         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4372         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4373         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4374         Cvar_RegisterVariable(&r_glsl);
4375         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4376         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4377         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4378         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4379         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4380         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4381         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4382         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4383         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4384         Cvar_RegisterVariable(&r_glsl_postprocess);
4385         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4386         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4387         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4388         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4389         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4390         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4391         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4392         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4393         Cvar_RegisterVariable(&r_celshading);
4394         Cvar_RegisterVariable(&r_celoutlines);
4395
4396         Cvar_RegisterVariable(&r_water);
4397         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4398         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4399         Cvar_RegisterVariable(&r_water_clippingplanebias);
4400         Cvar_RegisterVariable(&r_water_refractdistort);
4401         Cvar_RegisterVariable(&r_water_reflectdistort);
4402         Cvar_RegisterVariable(&r_water_scissormode);
4403         Cvar_RegisterVariable(&r_water_lowquality);
4404         Cvar_RegisterVariable(&r_water_hideplayer);
4405         Cvar_RegisterVariable(&r_water_fbo);
4406
4407         Cvar_RegisterVariable(&r_lerpsprites);
4408         Cvar_RegisterVariable(&r_lerpmodels);
4409         Cvar_RegisterVariable(&r_lerplightstyles);
4410         Cvar_RegisterVariable(&r_waterscroll);
4411         Cvar_RegisterVariable(&r_bloom);
4412         Cvar_RegisterVariable(&r_bloom_colorscale);
4413         Cvar_RegisterVariable(&r_bloom_brighten);
4414         Cvar_RegisterVariable(&r_bloom_blur);
4415         Cvar_RegisterVariable(&r_bloom_resolution);
4416         Cvar_RegisterVariable(&r_bloom_colorexponent);
4417         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4418         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4419         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4420         Cvar_RegisterVariable(&r_hdr_glowintensity);
4421         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4422         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4423         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4424         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4425         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4426         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4427         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4428         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4429         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4430         Cvar_RegisterVariable(&developer_texturelogging);
4431         Cvar_RegisterVariable(&gl_lightmaps);
4432         Cvar_RegisterVariable(&r_test);
4433         Cvar_RegisterVariable(&r_batch_multidraw);
4434         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4435         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4436         Cvar_RegisterVariable(&r_glsl_skeletal);
4437         Cvar_RegisterVariable(&r_glsl_saturation);
4438         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4439         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4440         Cvar_RegisterVariable(&r_framedatasize);
4441         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4442                 Cvar_RegisterVariable(&r_buffermegs[i]);
4443         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4444         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4445                 Cvar_SetValue("r_fullbrights", 0);
4446 #ifdef DP_MOBILETOUCH
4447         // GLES devices have terrible depth precision in general, so...
4448         Cvar_SetValueQuick(&r_nearclip, 4);
4449         Cvar_SetValueQuick(&r_farclip_base, 4096);
4450         Cvar_SetValueQuick(&r_farclip_world, 0);
4451         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4452 #endif
4453         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4454 }
4455
4456 void Render_Init(void)
4457 {
4458         gl_backend_init();
4459         R_Textures_Init();
4460         GL_Main_Init();
4461         Font_Init();
4462         GL_Draw_Init();
4463         R_Shadow_Init();
4464         R_Sky_Init();
4465         GL_Surf_Init();
4466         Sbar_Init();
4467         R_Particles_Init();
4468         R_Explosion_Init();
4469         R_LightningBeams_Init();
4470         Mod_RenderInit();
4471 }
4472
4473 /*
4474 ===============
4475 GL_Init
4476 ===============
4477 */
4478 #ifndef USE_GLES2
4479 extern char *ENGINE_EXTENSIONS;
4480 void GL_Init (void)
4481 {
4482         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4483         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4484         gl_version = (const char *)qglGetString(GL_VERSION);
4485         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4486
4487         if (!gl_extensions)
4488                 gl_extensions = "";
4489         if (!gl_platformextensions)
4490                 gl_platformextensions = "";
4491
4492         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4493         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4494         Con_Printf("GL_VERSION: %s\n", gl_version);
4495         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4496         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4497
4498         VID_CheckExtensions();
4499
4500         // LordHavoc: report supported extensions
4501 #ifdef CONFIG_MENU
4502         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4503 #else
4504         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4505 #endif
4506
4507         // clear to black (loading plaque will be seen over this)
4508         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4509 }
4510 #endif
4511
4512 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4513 {
4514         int i;
4515         mplane_t *p;
4516         if (r_trippy.integer)
4517                 return false;
4518         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4519         {
4520                 p = r_refdef.view.frustum + i;
4521                 switch(p->signbits)
4522                 {
4523                 default:
4524                 case 0:
4525                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4526                                 return true;
4527                         break;
4528                 case 1:
4529                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4530                                 return true;
4531                         break;
4532                 case 2:
4533                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4534                                 return true;
4535                         break;
4536                 case 3:
4537                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4538                                 return true;
4539                         break;
4540                 case 4:
4541                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4542                                 return true;
4543                         break;
4544                 case 5:
4545                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4546                                 return true;
4547                         break;
4548                 case 6:
4549                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4550                                 return true;
4551                         break;
4552                 case 7:
4553                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4554                                 return true;
4555                         break;
4556                 }
4557         }
4558         return false;
4559 }
4560
4561 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4562 {
4563         int i;
4564         const mplane_t *p;
4565         if (r_trippy.integer)
4566                 return false;
4567         for (i = 0;i < numplanes;i++)
4568         {
4569                 p = planes + i;
4570                 switch(p->signbits)
4571                 {
4572                 default:
4573                 case 0:
4574                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4575                                 return true;
4576                         break;
4577                 case 1:
4578                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4579                                 return true;
4580                         break;
4581                 case 2:
4582                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4583                                 return true;
4584                         break;
4585                 case 3:
4586                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4587                                 return true;
4588                         break;
4589                 case 4:
4590                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4591                                 return true;
4592                         break;
4593                 case 5:
4594                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4595                                 return true;
4596                         break;
4597                 case 6:
4598                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4599                                 return true;
4600                         break;
4601                 case 7:
4602                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4603                                 return true;
4604                         break;
4605                 }
4606         }
4607         return false;
4608 }
4609
4610 //==================================================================================
4611
4612 // LordHavoc: this stores temporary data used within the same frame
4613
4614 typedef struct r_framedata_mem_s
4615 {
4616         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4617         size_t size; // how much usable space
4618         size_t current; // how much space in use
4619         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4620         size_t wantedsize; // how much space was allocated
4621         unsigned char *data; // start of real data (16byte aligned)
4622 }
4623 r_framedata_mem_t;
4624
4625 static r_framedata_mem_t *r_framedata_mem;
4626
4627 void R_FrameData_Reset(void)
4628 {
4629         while (r_framedata_mem)
4630         {
4631                 r_framedata_mem_t *next = r_framedata_mem->purge;
4632                 Mem_Free(r_framedata_mem);
4633                 r_framedata_mem = next;
4634         }
4635 }
4636
4637 static void R_FrameData_Resize(qboolean mustgrow)
4638 {
4639         size_t wantedsize;
4640         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4641         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4642         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4643         {
4644                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4645                 newmem->wantedsize = wantedsize;
4646                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4647                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4648                 newmem->current = 0;
4649                 newmem->mark = 0;
4650                 newmem->purge = r_framedata_mem;
4651                 r_framedata_mem = newmem;
4652         }
4653 }
4654
4655 void R_FrameData_NewFrame(void)
4656 {
4657         R_FrameData_Resize(false);
4658         if (!r_framedata_mem)
4659                 return;
4660         // if we ran out of space on the last frame, free the old memory now
4661         while (r_framedata_mem->purge)
4662         {
4663                 // repeatedly remove the second item in the list, leaving only head
4664                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4665                 Mem_Free(r_framedata_mem->purge);
4666                 r_framedata_mem->purge = next;
4667         }
4668         // reset the current mem pointer
4669         r_framedata_mem->current = 0;
4670         r_framedata_mem->mark = 0;
4671 }
4672
4673 void *R_FrameData_Alloc(size_t size)
4674 {
4675         void *data;
4676         float newvalue;
4677
4678         // align to 16 byte boundary - the data pointer is already aligned, so we
4679         // only need to ensure the size of every allocation is also aligned
4680         size = (size + 15) & ~15;
4681
4682         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4683         {
4684                 // emergency - we ran out of space, allocate more memory
4685                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4686                 newvalue = r_framedatasize.value * 2.0f;
4687                 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4688                 if (sizeof(size_t) >= 8)
4689                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4690                 else
4691                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4692                 // this might not be a growing it, but we'll allocate another buffer every time
4693                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4694                 R_FrameData_Resize(true);
4695         }
4696
4697         data = r_framedata_mem->data + r_framedata_mem->current;
4698         r_framedata_mem->current += size;
4699
4700         // count the usage for stats
4701         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4702         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4703
4704         return (void *)data;
4705 }
4706
4707 void *R_FrameData_Store(size_t size, void *data)
4708 {
4709         void *d = R_FrameData_Alloc(size);
4710         if (d && data)
4711                 memcpy(d, data, size);
4712         return d;
4713 }
4714
4715 void R_FrameData_SetMark(void)
4716 {
4717         if (!r_framedata_mem)
4718                 return;
4719         r_framedata_mem->mark = r_framedata_mem->current;
4720 }
4721
4722 void R_FrameData_ReturnToMark(void)
4723 {
4724         if (!r_framedata_mem)
4725                 return;
4726         r_framedata_mem->current = r_framedata_mem->mark;
4727 }
4728
4729 //==================================================================================
4730
4731 // avoid reusing the same buffer objects on consecutive frames
4732 #define R_BUFFERDATA_CYCLE 3
4733
4734 typedef struct r_bufferdata_buffer_s
4735 {
4736         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4737         size_t size; // how much usable space
4738         size_t current; // how much space in use
4739         r_meshbuffer_t *buffer; // the buffer itself
4740 }
4741 r_bufferdata_buffer_t;
4742
4743 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4744 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4745
4746 /// frees all dynamic buffers
4747 void R_BufferData_Reset(void)
4748 {
4749         int cycle, type;
4750         r_bufferdata_buffer_t **p, *mem;
4751         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4752         {
4753                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4754                 {
4755                         // free all buffers
4756                         p = &r_bufferdata_buffer[cycle][type];
4757                         while (*p)
4758                         {
4759                                 mem = *p;
4760                                 *p = (*p)->purge;
4761                                 if (mem->buffer)
4762                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4763                                 Mem_Free(mem);
4764                         }
4765                 }
4766         }
4767 }
4768
4769 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4770 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4771 {
4772         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4773         size_t size;
4774         float newvalue = r_buffermegs[type].value;
4775
4776         // increase the cvar if we have to (but only if we already have a mem)
4777         if (mustgrow && mem)
4778                 newvalue *= 2.0f;
4779         newvalue = bound(0.25f, newvalue, 256.0f);
4780         while (newvalue * 1024*1024 < minsize)
4781                 newvalue *= 2.0f;
4782
4783         // clamp the cvar to valid range
4784         newvalue = bound(0.25f, newvalue, 256.0f);
4785         if (r_buffermegs[type].value != newvalue)
4786                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4787
4788         // calculate size in bytes
4789         size = (size_t)(newvalue * 1024*1024);
4790         size = bound(131072, size, 256*1024*1024);
4791
4792         // allocate a new buffer if the size is different (purge old one later)
4793         // or if we were told we must grow the buffer
4794         if (!mem || mem->size != size || mustgrow)
4795         {
4796                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4797                 mem->size = size;
4798                 mem->current = 0;
4799                 if (type == R_BUFFERDATA_VERTEX)
4800                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4801                 else if (type == R_BUFFERDATA_INDEX16)
4802                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4803                 else if (type == R_BUFFERDATA_INDEX32)
4804                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4805                 else if (type == R_BUFFERDATA_UNIFORM)
4806                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4807                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4808                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4809         }
4810 }
4811
4812 void R_BufferData_NewFrame(void)
4813 {
4814         int type;
4815         r_bufferdata_buffer_t **p, *mem;
4816         // cycle to the next frame's buffers
4817         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4818         // if we ran out of space on the last time we used these buffers, free the old memory now
4819         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4820         {
4821                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4822                 {
4823                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4824                         // free all but the head buffer, this is how we recycle obsolete
4825                         // buffers after they are no longer in use
4826                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4827                         while (*p)
4828                         {
4829                                 mem = *p;
4830                                 *p = (*p)->purge;
4831                                 if (mem->buffer)
4832                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4833                                 Mem_Free(mem);
4834                         }
4835                         // reset the current offset
4836                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4837                 }
4838         }
4839 }
4840
4841 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4842 {
4843         r_bufferdata_buffer_t *mem;
4844         int offset = 0;
4845         int padsize;
4846
4847         *returnbufferoffset = 0;
4848
4849         // align size to a byte boundary appropriate for the buffer type, this
4850         // makes all allocations have aligned start offsets
4851         if (type == R_BUFFERDATA_UNIFORM)
4852                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4853         else
4854                 padsize = (datasize + 15) & ~15;
4855
4856         // if we ran out of space in this buffer we must allocate a new one
4857         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4858                 R_BufferData_Resize(type, true, padsize);
4859
4860         // if the resize did not give us enough memory, fail
4861         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4862                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4863
4864         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4865         offset = (int)mem->current;
4866         mem->current += padsize;
4867
4868         // upload the data to the buffer at the chosen offset
4869         if (offset == 0)
4870                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4871         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4872
4873         // count the usage for stats
4874         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4875         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4876
4877         // return the buffer offset
4878         *returnbufferoffset = offset;
4879
4880         return mem->buffer;
4881 }
4882
4883 //==================================================================================
4884
4885 // LordHavoc: animcache originally written by Echon, rewritten since then
4886
4887 /**
4888  * Animation cache prevents re-generating mesh data for an animated model
4889  * multiple times in one frame for lighting, shadowing, reflections, etc.
4890  */
4891
4892 void R_AnimCache_Free(void)
4893 {
4894 }
4895
4896 void R_AnimCache_ClearCache(void)
4897 {
4898         int i;
4899         entity_render_t *ent;
4900
4901         for (i = 0;i < r_refdef.scene.numentities;i++)
4902         {
4903                 ent = r_refdef.scene.entities[i];
4904                 ent->animcache_vertex3f = NULL;
4905                 ent->animcache_vertex3f_vertexbuffer = NULL;
4906                 ent->animcache_vertex3f_bufferoffset = 0;
4907                 ent->animcache_normal3f = NULL;
4908                 ent->animcache_normal3f_vertexbuffer = NULL;
4909                 ent->animcache_normal3f_bufferoffset = 0;
4910                 ent->animcache_svector3f = NULL;
4911                 ent->animcache_svector3f_vertexbuffer = NULL;
4912                 ent->animcache_svector3f_bufferoffset = 0;
4913                 ent->animcache_tvector3f = NULL;
4914                 ent->animcache_tvector3f_vertexbuffer = NULL;
4915                 ent->animcache_tvector3f_bufferoffset = 0;
4916                 ent->animcache_vertexmesh = NULL;
4917                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4918                 ent->animcache_vertexmesh_bufferoffset = 0;
4919                 ent->animcache_skeletaltransform3x4 = NULL;
4920                 ent->animcache_skeletaltransform3x4buffer = NULL;
4921                 ent->animcache_skeletaltransform3x4offset = 0;
4922                 ent->animcache_skeletaltransform3x4size = 0;
4923         }
4924 }
4925
4926 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4927 {
4928         int i;
4929
4930         // check if we need the meshbuffers
4931         if (!vid.useinterleavedarrays)
4932                 return;
4933
4934         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4935                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4936         // TODO: upload vertexbuffer?
4937         if (ent->animcache_vertexmesh)
4938         {
4939                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4940                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4941                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4942                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4943                 for (i = 0;i < numvertices;i++)
4944                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4945                 if (ent->animcache_svector3f)
4946                         for (i = 0;i < numvertices;i++)
4947                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4948                 if (ent->animcache_tvector3f)
4949                         for (i = 0;i < numvertices;i++)
4950                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4951                 if (ent->animcache_normal3f)
4952                         for (i = 0;i < numvertices;i++)
4953                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4954         }
4955 }
4956
4957 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4958 {
4959         dp_model_t *model = ent->model;
4960         int numvertices;
4961
4962         // see if this ent is worth caching
4963         if (!model || !model->Draw || !model->AnimateVertices)
4964                 return false;
4965         // nothing to cache if it contains no animations and has no skeleton
4966         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4967                 return false;
4968         // see if it is already cached for gpuskeletal
4969         if (ent->animcache_skeletaltransform3x4)
4970                 return false;
4971         // see if it is already cached as a mesh
4972         if (ent->animcache_vertex3f)
4973         {
4974                 // check if we need to add normals or tangents
4975                 if (ent->animcache_normal3f)
4976                         wantnormals = false;
4977                 if (ent->animcache_svector3f)
4978                         wanttangents = false;
4979                 if (!wantnormals && !wanttangents)
4980                         return false;
4981         }
4982
4983         // check which kind of cache we need to generate
4984         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4985         {
4986                 // cache the skeleton so the vertex shader can use it
4987                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4988                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4989                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4990                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4991                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4992                 // note: this can fail if the buffer is at the grow limit
4993                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4994                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4995         }
4996         else if (ent->animcache_vertex3f)
4997         {
4998                 // mesh was already cached but we may need to add normals/tangents
4999                 // (this only happens with multiple views, reflections, cameras, etc)
5000                 if (wantnormals || wanttangents)
5001                 {
5002                         numvertices = model->surfmesh.num_vertices;
5003                         if (wantnormals)
5004                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5005                         if (wanttangents)
5006                         {
5007                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5008                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5009                         }
5010                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5011                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5012                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5013                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5014                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5015                 }
5016         }
5017         else
5018         {
5019                 // generate mesh cache
5020                 numvertices = model->surfmesh.num_vertices;
5021                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5022                 if (wantnormals)
5023                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5024                 if (wanttangents)
5025                 {
5026                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5027                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5028                 }
5029                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5030                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5031                 if (wantnormals || wanttangents)
5032                 {
5033                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5034                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5035                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5036                 }
5037                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5038                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5039                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5040         }
5041         return true;
5042 }
5043
5044 void R_AnimCache_CacheVisibleEntities(void)
5045 {
5046         int i;
5047         qboolean wantnormals = true;
5048         qboolean wanttangents = !r_showsurfaces.integer;
5049
5050         switch(vid.renderpath)
5051         {
5052         case RENDERPATH_GL20:
5053         case RENDERPATH_D3D9:
5054         case RENDERPATH_D3D10:
5055         case RENDERPATH_D3D11:
5056         case RENDERPATH_GLES2:
5057                 break;
5058         case RENDERPATH_GL11:
5059         case RENDERPATH_GL13:
5060         case RENDERPATH_GLES1:
5061                 wanttangents = false;
5062                 break;
5063         case RENDERPATH_SOFT:
5064                 break;
5065         }
5066
5067         if (r_shownormals.integer)
5068                 wanttangents = wantnormals = true;
5069
5070         // TODO: thread this
5071         // NOTE: R_PrepareRTLights() also caches entities
5072
5073         for (i = 0;i < r_refdef.scene.numentities;i++)
5074                 if (r_refdef.viewcache.entityvisible[i])
5075                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5076 }
5077
5078 //==================================================================================
5079
5080 extern cvar_t r_overheadsprites_pushback;
5081
5082 static void R_View_UpdateEntityLighting (void)
5083 {
5084         int i;
5085         entity_render_t *ent;
5086         vec3_t tempdiffusenormal, avg;
5087         vec_t f, fa, fd, fdd;
5088         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5089
5090         for (i = 0;i < r_refdef.scene.numentities;i++)
5091         {
5092                 ent = r_refdef.scene.entities[i];
5093
5094                 // skip unseen models
5095                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5096                         continue;
5097
5098                 // skip bsp models
5099                 if (ent->model && ent->model == cl.worldmodel)
5100                 {
5101                         // TODO: use modellight for r_ambient settings on world?
5102                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5103                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5104                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5105                         continue;
5106                 }
5107                 
5108                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5109                 {
5110                         // aleady updated by CSQC
5111                         // TODO: force modellight on BSP models in this case?
5112                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5113                 }
5114                 else
5115                 {
5116                         // fetch the lighting from the worldmodel data
5117                         VectorClear(ent->modellight_ambient);
5118                         VectorClear(ent->modellight_diffuse);
5119                         VectorClear(tempdiffusenormal);
5120                         if (ent->flags & RENDER_LIGHT)
5121                         {
5122                                 vec3_t org;
5123                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5124
5125                                 // complete lightning for lit sprites
5126                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5127                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5128                                 {
5129                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5130                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5131                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5132                                 }
5133                                 else
5134                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5135
5136                                 if(ent->flags & RENDER_EQUALIZE)
5137                                 {
5138                                         // first fix up ambient lighting...
5139                                         if(r_equalize_entities_minambient.value > 0)
5140                                         {
5141                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5142                                                 if(fd > 0)
5143                                                 {
5144                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5145                                                         if(fa < r_equalize_entities_minambient.value * fd)
5146                                                         {
5147                                                                 // solve:
5148                                                                 //   fa'/fd' = minambient
5149                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5150                                                                 //   ...
5151                                                                 //   fa' = fd' * minambient
5152                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5153                                                                 //   ...
5154                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5155                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5156                                                                 //   ...
5157                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5158                                                                 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
5159                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5160                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5161                                                         }
5162                                                 }
5163                                         }
5164
5165                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5166                                         {
5167                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5168                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5169                                                 f = fa + 0.25 * fd;
5170                                                 if(f > 0)
5171                                                 {
5172                                                         // adjust brightness and saturation to target
5173                                                         avg[0] = avg[1] = avg[2] = fa / f;
5174                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5175                                                         avg[0] = avg[1] = avg[2] = fd / f;
5176                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5177                                                 }
5178                                         }
5179                                 }
5180                         }
5181                         else // highly rare
5182                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5183                 }
5184
5185                 // move the light direction into modelspace coordinates for lighting code
5186                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5187                 if(VectorLength2(ent->modellight_lightdir) == 0)
5188                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5189                 VectorNormalize(ent->modellight_lightdir);
5190         }
5191 }
5192
5193 #define MAX_LINEOFSIGHTTRACES 64
5194
5195 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5196 {
5197         int i;
5198         vec3_t boxmins, boxmaxs;
5199         vec3_t start;
5200         vec3_t end;
5201         dp_model_t *model = r_refdef.scene.worldmodel;
5202
5203         if (!model || !model->brush.TraceLineOfSight)
5204                 return true;
5205
5206         // expand the box a little
5207         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5208         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5209         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5210         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5211         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5212         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5213
5214         // return true if eye is inside enlarged box
5215         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5216                 return true;
5217
5218         // try center
5219         VectorCopy(eye, start);
5220         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5221         if (model->brush.TraceLineOfSight(model, start, end))
5222                 return true;
5223
5224         // try various random positions
5225         for (i = 0;i < numsamples;i++)
5226         {
5227                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5228                 if (model->brush.TraceLineOfSight(model, start, end))
5229                         return true;
5230         }
5231
5232         return false;
5233 }
5234
5235
5236 static void R_View_UpdateEntityVisible (void)
5237 {
5238         int i;
5239         int renderimask;
5240         int samples;
5241         entity_render_t *ent;
5242
5243         if (r_refdef.envmap || r_fb.water.hideplayer)
5244                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5245         else if (chase_active.integer || r_fb.water.renderingscene)
5246                 renderimask = RENDER_VIEWMODEL;
5247         else
5248                 renderimask = RENDER_EXTERIORMODEL;
5249         if (!r_drawviewmodel.integer)
5250                 renderimask |= RENDER_VIEWMODEL;
5251         if (!r_drawexteriormodel.integer)
5252                 renderimask |= RENDER_EXTERIORMODEL;
5253         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5254         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5255         {
5256                 // worldmodel can check visibility
5257                 for (i = 0;i < r_refdef.scene.numentities;i++)
5258                 {
5259                         ent = r_refdef.scene.entities[i];
5260                         if (!(ent->flags & renderimask))
5261                         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)))
5262                         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))
5263                                 r_refdef.viewcache.entityvisible[i] = true;
5264                 }
5265         }
5266         else
5267         {
5268                 // no worldmodel or it can't check visibility
5269                 for (i = 0;i < r_refdef.scene.numentities;i++)
5270                 {
5271                         ent = r_refdef.scene.entities[i];
5272                         if (!(ent->flags & renderimask))
5273                         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)))
5274                                 r_refdef.viewcache.entityvisible[i] = true;
5275                 }
5276         }
5277         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5278                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5279         {
5280                 for (i = 0;i < r_refdef.scene.numentities;i++)
5281                 {
5282                         if (!r_refdef.viewcache.entityvisible[i])
5283                                 continue;
5284                         ent = r_refdef.scene.entities[i];
5285                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5286                         {
5287                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5288                                 if (samples < 0)
5289                                         continue; // temp entities do pvs only
5290                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5291                                         ent->last_trace_visibility = realtime;
5292                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5293                                         r_refdef.viewcache.entityvisible[i] = 0;
5294                         }
5295                 }
5296         }
5297 }
5298
5299 /// only used if skyrendermasked, and normally returns false
5300 static int R_DrawBrushModelsSky (void)
5301 {
5302         int i, sky;
5303         entity_render_t *ent;
5304
5305         sky = false;
5306         for (i = 0;i < r_refdef.scene.numentities;i++)
5307         {
5308                 if (!r_refdef.viewcache.entityvisible[i])
5309                         continue;
5310                 ent = r_refdef.scene.entities[i];
5311                 if (!ent->model || !ent->model->DrawSky)
5312                         continue;
5313                 ent->model->DrawSky(ent);
5314                 sky = true;
5315         }
5316         return sky;
5317 }
5318
5319 static void R_DrawNoModel(entity_render_t *ent);
5320 static void R_DrawModels(void)
5321 {
5322         int i;
5323         entity_render_t *ent;
5324
5325         for (i = 0;i < r_refdef.scene.numentities;i++)
5326         {
5327                 if (!r_refdef.viewcache.entityvisible[i])
5328                         continue;
5329                 ent = r_refdef.scene.entities[i];
5330                 r_refdef.stats[r_stat_entities]++;
5331                 /*
5332                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5333                 {
5334                         vec3_t f, l, u, o;
5335                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5336                         Con_Printf("R_DrawModels\n");
5337                         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]);
5338                         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);
5339                         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);
5340                 }
5341                 */
5342                 if (ent->model && ent->model->Draw != NULL)
5343                         ent->model->Draw(ent);
5344                 else
5345                         R_DrawNoModel(ent);
5346         }
5347 }
5348
5349 static void R_DrawModelsDepth(void)
5350 {
5351         int i;
5352         entity_render_t *ent;
5353
5354         for (i = 0;i < r_refdef.scene.numentities;i++)
5355         {
5356                 if (!r_refdef.viewcache.entityvisible[i])
5357                         continue;
5358                 ent = r_refdef.scene.entities[i];
5359                 if (ent->model && ent->model->DrawDepth != NULL)
5360                         ent->model->DrawDepth(ent);
5361         }
5362 }
5363
5364 static void R_DrawModelsDebug(void)
5365 {
5366         int i;
5367         entity_render_t *ent;
5368
5369         for (i = 0;i < r_refdef.scene.numentities;i++)
5370         {
5371                 if (!r_refdef.viewcache.entityvisible[i])
5372                         continue;
5373                 ent = r_refdef.scene.entities[i];
5374                 if (ent->model && ent->model->DrawDebug != NULL)
5375                         ent->model->DrawDebug(ent);
5376         }
5377 }
5378
5379 static void R_DrawModelsAddWaterPlanes(void)
5380 {
5381         int i;
5382         entity_render_t *ent;
5383
5384         for (i = 0;i < r_refdef.scene.numentities;i++)
5385         {
5386                 if (!r_refdef.viewcache.entityvisible[i])
5387                         continue;
5388                 ent = r_refdef.scene.entities[i];
5389                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5390                         ent->model->DrawAddWaterPlanes(ent);
5391         }
5392 }
5393
5394 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}};
5395
5396 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5397 {
5398         if (r_hdr_irisadaptation.integer)
5399         {
5400                 vec3_t p;
5401                 vec3_t ambient;
5402                 vec3_t diffuse;
5403                 vec3_t diffusenormal;
5404                 vec3_t forward;
5405                 vec_t brightness = 0.0f;
5406                 vec_t goal;
5407                 vec_t current;
5408                 vec_t d;
5409                 int c;
5410                 VectorCopy(r_refdef.view.forward, forward);
5411                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5412                 {
5413                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5414                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5415                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5416                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5417                         d = DotProduct(forward, diffusenormal);
5418                         brightness += VectorLength(ambient);
5419                         if (d > 0)
5420                                 brightness += d * VectorLength(diffuse);
5421                 }
5422                 brightness *= 1.0f / c;
5423                 brightness += 0.00001f; // make sure it's never zero
5424                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5425                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5426                 current = r_hdr_irisadaptation_value.value;
5427                 if (current < goal)
5428                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5429                 else if (current > goal)
5430                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5431                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5432                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5433         }
5434         else if (r_hdr_irisadaptation_value.value != 1.0f)
5435                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5436 }
5437
5438 static void R_View_SetFrustum(const int *scissor)
5439 {
5440         int i;
5441         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5442         vec3_t forward, left, up, origin, v;
5443
5444         if(scissor)
5445         {
5446                 // flipped x coordinates (because x points left here)
5447                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5448                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5449
5450                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5451                 switch(vid.renderpath)
5452                 {
5453                         case RENDERPATH_D3D9:
5454                         case RENDERPATH_D3D10:
5455                         case RENDERPATH_D3D11:
5456                                 // non-flipped y coordinates
5457                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5458                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5459                                 break;
5460                         case RENDERPATH_SOFT:
5461                         case RENDERPATH_GL11:
5462                         case RENDERPATH_GL13:
5463                         case RENDERPATH_GL20:
5464                         case RENDERPATH_GLES1:
5465                         case RENDERPATH_GLES2:
5466                                 // non-flipped y coordinates
5467                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5468                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5469                                 break;
5470                 }
5471         }
5472
5473         // we can't trust r_refdef.view.forward and friends in reflected scenes
5474         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5475
5476 #if 0
5477         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5478         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5479         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5480         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5481         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5482         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5483         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5484         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5485         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5486         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5487         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5488         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5489 #endif
5490
5491 #if 0
5492         zNear = r_refdef.nearclip;
5493         nudge = 1.0 - 1.0 / (1<<23);
5494         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5495         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5496         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5497         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5498         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5499         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5500         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5501         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5502 #endif
5503
5504
5505
5506 #if 0
5507         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5508         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5509         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5510         r_refdef.view.frustum[0].dist = m[15] - m[12];
5511
5512         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5513         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5514         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5515         r_refdef.view.frustum[1].dist = m[15] + m[12];
5516
5517         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5518         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5519         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5520         r_refdef.view.frustum[2].dist = m[15] - m[13];
5521
5522         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5523         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5524         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5525         r_refdef.view.frustum[3].dist = m[15] + m[13];
5526
5527         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5528         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5529         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5530         r_refdef.view.frustum[4].dist = m[15] - m[14];
5531
5532         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5533         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5534         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5535         r_refdef.view.frustum[5].dist = m[15] + m[14];
5536 #endif
5537
5538         if (r_refdef.view.useperspective)
5539         {
5540                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5541                 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]);
5542                 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]);
5543                 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]);
5544                 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]);
5545
5546                 // then the normals from the corners relative to origin
5547                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5548                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5549                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5550                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5551
5552                 // in a NORMAL view, forward cross left == up
5553                 // in a REFLECTED view, forward cross left == down
5554                 // so our cross products above need to be adjusted for a left handed coordinate system
5555                 CrossProduct(forward, left, v);
5556                 if(DotProduct(v, up) < 0)
5557                 {
5558                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5559                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5560                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5561                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5562                 }
5563
5564                 // Leaving those out was a mistake, those were in the old code, and they
5565                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5566                 // I couldn't reproduce it after adding those normalizations. --blub
5567                 VectorNormalize(r_refdef.view.frustum[0].normal);
5568                 VectorNormalize(r_refdef.view.frustum[1].normal);
5569                 VectorNormalize(r_refdef.view.frustum[2].normal);
5570                 VectorNormalize(r_refdef.view.frustum[3].normal);
5571
5572                 // make the corners absolute
5573                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5574                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5575                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5576                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5577
5578                 // one more normal
5579                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5580
5581                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5582                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5583                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5584                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5585                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5586         }
5587         else
5588         {
5589                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5590                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5591                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5592                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5593                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5594                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5595                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5596                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5597                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5598                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5599         }
5600         r_refdef.view.numfrustumplanes = 5;
5601
5602         if (r_refdef.view.useclipplane)
5603         {
5604                 r_refdef.view.numfrustumplanes = 6;
5605                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5606         }
5607
5608         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5609                 PlaneClassify(r_refdef.view.frustum + i);
5610
5611         // LordHavoc: note to all quake engine coders, Quake had a special case
5612         // for 90 degrees which assumed a square view (wrong), so I removed it,
5613         // Quake2 has it disabled as well.
5614
5615         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5616         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5617         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5618         //PlaneClassify(&frustum[0]);
5619
5620         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5621         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5622         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5623         //PlaneClassify(&frustum[1]);
5624
5625         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5626         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5627         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5628         //PlaneClassify(&frustum[2]);
5629
5630         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5631         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5632         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5633         //PlaneClassify(&frustum[3]);
5634
5635         // nearclip plane
5636         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5637         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5638         //PlaneClassify(&frustum[4]);
5639 }
5640
5641 static void R_View_UpdateWithScissor(const int *myscissor)
5642 {
5643         R_Main_ResizeViewCache();
5644         R_View_SetFrustum(myscissor);
5645         R_View_WorldVisibility(r_refdef.view.useclipplane);
5646         R_View_UpdateEntityVisible();
5647         R_View_UpdateEntityLighting();
5648 }
5649
5650 static void R_View_Update(void)
5651 {
5652         R_Main_ResizeViewCache();
5653         R_View_SetFrustum(NULL);
5654         R_View_WorldVisibility(r_refdef.view.useclipplane);
5655         R_View_UpdateEntityVisible();
5656         R_View_UpdateEntityLighting();
5657 }
5658
5659 float viewscalefpsadjusted = 1.0f;
5660
5661 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5662 {
5663         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5664         scale = bound(0.03125f, scale, 1.0f);
5665         *outwidth = (int)ceil(width * scale);
5666         *outheight = (int)ceil(height * scale);
5667 }
5668
5669 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5670 {
5671         const float *customclipplane = NULL;
5672         float plane[4];
5673         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5674         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5675         {
5676                 // LordHavoc: couldn't figure out how to make this approach the
5677                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5678                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5679                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5680                         dist = r_refdef.view.clipplane.dist;
5681                 plane[0] = r_refdef.view.clipplane.normal[0];
5682                 plane[1] = r_refdef.view.clipplane.normal[1];
5683                 plane[2] = r_refdef.view.clipplane.normal[2];
5684                 plane[3] = -dist;
5685                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5686         }
5687
5688         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5689         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5690
5691         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5692         if (!r_refdef.view.useperspective)
5693                 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);
5694         else if (vid.stencil && r_useinfinitefarclip.integer)
5695                 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);
5696         else
5697                 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);
5698         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5699         R_SetViewport(&r_refdef.view.viewport);
5700         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5701         {
5702                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5703                 float screenplane[4];
5704                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5705                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5706                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5707                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5708                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5709         }
5710 }
5711
5712 void R_EntityMatrix(const matrix4x4_t *matrix)
5713 {
5714         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5715         {
5716                 gl_modelmatrixchanged = false;
5717                 gl_modelmatrix = *matrix;
5718                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5719                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5720                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5721                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5722                 CHECKGLERROR
5723                 switch(vid.renderpath)
5724                 {
5725                 case RENDERPATH_D3D9:
5726 #ifdef SUPPORTD3D
5727                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5728                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5729 #endif
5730                         break;
5731                 case RENDERPATH_D3D10:
5732                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5733                         break;
5734                 case RENDERPATH_D3D11:
5735                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5736                         break;
5737                 case RENDERPATH_GL11:
5738                 case RENDERPATH_GL13:
5739                 case RENDERPATH_GLES1:
5740 #ifndef USE_GLES2
5741                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5742 #endif
5743                         break;
5744                 case RENDERPATH_SOFT:
5745                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5746                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5747                         break;
5748                 case RENDERPATH_GL20:
5749                 case RENDERPATH_GLES2:
5750                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5751                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5752                         break;
5753                 }
5754         }
5755 }
5756
5757 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5758 {
5759         r_viewport_t viewport;
5760
5761         CHECKGLERROR
5762
5763         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5764         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);
5765         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5766         R_SetViewport(&viewport);
5767         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5768         GL_Color(1, 1, 1, 1);
5769         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5770         GL_BlendFunc(GL_ONE, GL_ZERO);
5771         GL_ScissorTest(false);
5772         GL_DepthMask(false);
5773         GL_DepthRange(0, 1);
5774         GL_DepthTest(false);
5775         GL_DepthFunc(GL_LEQUAL);
5776         R_EntityMatrix(&identitymatrix);
5777         R_Mesh_ResetTextureState();
5778         GL_PolygonOffset(0, 0);
5779         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5780         switch(vid.renderpath)
5781         {
5782         case RENDERPATH_GL11:
5783         case RENDERPATH_GL13:
5784         case RENDERPATH_GL20:
5785         case RENDERPATH_GLES1:
5786         case RENDERPATH_GLES2:
5787                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5788                 break;
5789         case RENDERPATH_D3D9:
5790         case RENDERPATH_D3D10:
5791         case RENDERPATH_D3D11:
5792         case RENDERPATH_SOFT:
5793                 break;
5794         }
5795         GL_CullFace(GL_NONE);
5796
5797         CHECKGLERROR
5798 }
5799
5800 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5801 {
5802         DrawQ_Finish();
5803
5804         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5805 }
5806
5807 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5808 {
5809         DrawQ_Finish();
5810
5811         R_SetupView(true, fbo, depthtexture, colortexture);
5812         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5813         GL_Color(1, 1, 1, 1);
5814         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5815         GL_BlendFunc(GL_ONE, GL_ZERO);
5816         GL_ScissorTest(true);
5817         GL_DepthMask(true);
5818         GL_DepthRange(0, 1);
5819         GL_DepthTest(true);
5820         GL_DepthFunc(GL_LEQUAL);
5821         R_EntityMatrix(&identitymatrix);
5822         R_Mesh_ResetTextureState();
5823         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5824         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5825         switch(vid.renderpath)
5826         {
5827         case RENDERPATH_GL11:
5828         case RENDERPATH_GL13:
5829         case RENDERPATH_GL20:
5830         case RENDERPATH_GLES1:
5831         case RENDERPATH_GLES2:
5832                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5833                 break;
5834         case RENDERPATH_D3D9:
5835         case RENDERPATH_D3D10:
5836         case RENDERPATH_D3D11:
5837         case RENDERPATH_SOFT:
5838                 break;
5839         }
5840         GL_CullFace(r_refdef.view.cullface_back);
5841 }
5842
5843 /*
5844 ================
5845 R_RenderView_UpdateViewVectors
5846 ================
5847 */
5848 void R_RenderView_UpdateViewVectors(void)
5849 {
5850         // break apart the view matrix into vectors for various purposes
5851         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5852         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5853         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5854         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5855         // make an inverted copy of the view matrix for tracking sprites
5856         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5857 }
5858
5859 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5860 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5861
5862 static void R_Water_StartFrame(void)
5863 {
5864         int i;
5865         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5866         r_waterstate_waterplane_t *p;
5867         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;
5868
5869         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5870                 return;
5871
5872         switch(vid.renderpath)
5873         {
5874         case RENDERPATH_GL20:
5875         case RENDERPATH_D3D9:
5876         case RENDERPATH_D3D10:
5877         case RENDERPATH_D3D11:
5878         case RENDERPATH_SOFT:
5879         case RENDERPATH_GLES2:
5880                 break;
5881         case RENDERPATH_GL11:
5882         case RENDERPATH_GL13:
5883         case RENDERPATH_GLES1:
5884                 return;
5885         }
5886
5887         // set waterwidth and waterheight to the water resolution that will be
5888         // used (often less than the screen resolution for faster rendering)
5889         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5890
5891         // calculate desired texture sizes
5892         // can't use water if the card does not support the texture size
5893         if (!r_water.integer || r_showsurfaces.integer)
5894                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5895         else if (vid.support.arb_texture_non_power_of_two)
5896         {
5897                 texturewidth = waterwidth;
5898                 textureheight = waterheight;
5899                 camerawidth = waterwidth;
5900                 cameraheight = waterheight;
5901         }
5902         else
5903         {
5904                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5905                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5906                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5907                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5908         }
5909
5910         // allocate textures as needed
5911         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))
5912         {
5913                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5914                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5915                 {
5916                         if (p->texture_refraction)
5917                                 R_FreeTexture(p->texture_refraction);
5918                         p->texture_refraction = NULL;
5919                         if (p->fbo_refraction)
5920                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5921                         p->fbo_refraction = 0;
5922                         if (p->texture_reflection)
5923                                 R_FreeTexture(p->texture_reflection);
5924                         p->texture_reflection = NULL;
5925                         if (p->fbo_reflection)
5926                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5927                         p->fbo_reflection = 0;
5928                         if (p->texture_camera)
5929                                 R_FreeTexture(p->texture_camera);
5930                         p->texture_camera = NULL;
5931                         if (p->fbo_camera)
5932                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5933                         p->fbo_camera = 0;
5934                 }
5935                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5936                 r_fb.water.texturewidth = texturewidth;
5937                 r_fb.water.textureheight = textureheight;
5938                 r_fb.water.camerawidth = camerawidth;
5939                 r_fb.water.cameraheight = cameraheight;
5940         }
5941
5942         if (r_fb.water.texturewidth)
5943         {
5944                 int scaledwidth, scaledheight;
5945
5946                 r_fb.water.enabled = true;
5947
5948                 // water resolution is usually reduced
5949                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5950                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5951                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5952
5953                 // set up variables that will be used in shader setup
5954                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5955                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5956                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5957                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5958         }
5959
5960         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5961         r_fb.water.numwaterplanes = 0;
5962 }
5963
5964 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5965 {
5966         int planeindex, bestplaneindex, vertexindex;
5967         vec3_t mins, maxs, normal, center, v, n;
5968         vec_t planescore, bestplanescore;
5969         mplane_t plane;
5970         r_waterstate_waterplane_t *p;
5971         texture_t *t = R_GetCurrentTexture(surface->texture);
5972
5973         rsurface.texture = t;
5974         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5975         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5976         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5977                 return;
5978         // average the vertex normals, find the surface bounds (after deformvertexes)
5979         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5980         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5981         VectorCopy(n, normal);
5982         VectorCopy(v, mins);
5983         VectorCopy(v, maxs);
5984         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5985         {
5986                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5987                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5988                 VectorAdd(normal, n, normal);
5989                 mins[0] = min(mins[0], v[0]);
5990                 mins[1] = min(mins[1], v[1]);
5991                 mins[2] = min(mins[2], v[2]);
5992                 maxs[0] = max(maxs[0], v[0]);
5993                 maxs[1] = max(maxs[1], v[1]);
5994                 maxs[2] = max(maxs[2], v[2]);
5995         }
5996         VectorNormalize(normal);
5997         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5998
5999         VectorCopy(normal, plane.normal);
6000         VectorNormalize(plane.normal);
6001         plane.dist = DotProduct(center, plane.normal);
6002         PlaneClassify(&plane);
6003         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6004         {
6005                 // skip backfaces (except if nocullface is set)
6006 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6007 //                      return;
6008                 VectorNegate(plane.normal, plane.normal);
6009                 plane.dist *= -1;
6010                 PlaneClassify(&plane);
6011         }
6012
6013
6014         // find a matching plane if there is one
6015         bestplaneindex = -1;
6016         bestplanescore = 1048576.0f;
6017         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6018         {
6019                 if(p->camera_entity == t->camera_entity)
6020                 {
6021                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6022                         if (bestplaneindex < 0 || bestplanescore > planescore)
6023                         {
6024                                 bestplaneindex = planeindex;
6025                                 bestplanescore = planescore;
6026                         }
6027                 }
6028         }
6029         planeindex = bestplaneindex;
6030
6031         // if this surface does not fit any known plane rendered this frame, add one
6032         if (planeindex < 0 || bestplanescore > 0.001f)
6033         {
6034                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6035                 {
6036                         // store the new plane
6037                         planeindex = r_fb.water.numwaterplanes++;
6038                         p = r_fb.water.waterplanes + planeindex;
6039                         p->plane = plane;
6040                         // clear materialflags and pvs
6041                         p->materialflags = 0;
6042                         p->pvsvalid = false;
6043                         p->camera_entity = t->camera_entity;
6044                         VectorCopy(mins, p->mins);
6045                         VectorCopy(maxs, p->maxs);
6046                 }
6047                 else
6048                 {
6049                         // We're totally screwed.
6050                         return;
6051                 }
6052         }
6053         else
6054         {
6055                 // merge mins/maxs when we're adding this surface to the plane
6056                 p = r_fb.water.waterplanes + planeindex;
6057                 p->mins[0] = min(p->mins[0], mins[0]);
6058                 p->mins[1] = min(p->mins[1], mins[1]);
6059                 p->mins[2] = min(p->mins[2], mins[2]);
6060                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6061                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6062                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6063         }
6064         // merge this surface's materialflags into the waterplane
6065         p->materialflags |= t->currentmaterialflags;
6066         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6067         {
6068                 // merge this surface's PVS into the waterplane
6069                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6070                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6071                 {
6072                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6073                         p->pvsvalid = true;
6074                 }
6075         }
6076 }
6077
6078 extern cvar_t r_drawparticles;
6079 extern cvar_t r_drawdecals;
6080
6081 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6082 {
6083         int myscissor[4];
6084         r_refdef_view_t originalview;
6085         r_refdef_view_t myview;
6086         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;
6087         r_waterstate_waterplane_t *p;
6088         vec3_t visorigin;
6089         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;
6090         char vabuf[1024];
6091
6092         originalview = r_refdef.view;
6093
6094         // lowquality hack, temporarily shut down some cvars and restore afterwards
6095         qualityreduction = r_water_lowquality.integer;
6096         if (qualityreduction > 0)
6097         {
6098                 if (qualityreduction >= 1)
6099                 {
6100                         old_r_shadows = r_shadows.integer;
6101                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6102                         old_r_dlight = r_shadow_realtime_dlight.integer;
6103                         Cvar_SetValueQuick(&r_shadows, 0);
6104                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6105                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6106                 }
6107                 if (qualityreduction >= 2)
6108                 {
6109                         old_r_dynamic = r_dynamic.integer;
6110                         old_r_particles = r_drawparticles.integer;
6111                         old_r_decals = r_drawdecals.integer;
6112                         Cvar_SetValueQuick(&r_dynamic, 0);
6113                         Cvar_SetValueQuick(&r_drawparticles, 0);
6114                         Cvar_SetValueQuick(&r_drawdecals, 0);
6115                 }
6116         }
6117
6118         // make sure enough textures are allocated
6119         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6120         {
6121                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6122                         continue;
6123                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6124                 {
6125                         if (!p->texture_refraction)
6126                                 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);
6127                         if (!p->texture_refraction)
6128                                 goto error;
6129                         if (usewaterfbo)
6130                         {
6131                                 if (r_fb.water.depthtexture == NULL)
6132                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6133                                 if (p->fbo_refraction == 0)
6134                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6135                         }
6136                 }
6137                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6138                 {
6139                         if (!p->texture_camera)
6140                                 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);
6141                         if (!p->texture_camera)
6142                                 goto error;
6143                         if (usewaterfbo)
6144                         {
6145                                 if (r_fb.water.depthtexture == NULL)
6146                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6147                                 if (p->fbo_camera == 0)
6148                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6149                         }
6150                 }
6151
6152                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6153                 {
6154                         if (!p->texture_reflection)
6155                                 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);
6156                         if (!p->texture_reflection)
6157                                 goto error;
6158                         if (usewaterfbo)
6159                         {
6160                                 if (r_fb.water.depthtexture == NULL)
6161                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6162                                 if (p->fbo_reflection == 0)
6163                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6164                         }
6165                 }
6166         }
6167
6168         // render views
6169         r_refdef.view = originalview;
6170         r_refdef.view.showdebug = false;
6171         r_refdef.view.width = r_fb.water.waterwidth;
6172         r_refdef.view.height = r_fb.water.waterheight;
6173         r_refdef.view.useclipplane = true;
6174         myview = r_refdef.view;
6175         r_fb.water.renderingscene = true;
6176         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6177         {
6178                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6179                         continue;
6180                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6181                 {
6182                         r_refdef.view = myview;
6183                         if(r_water_scissormode.integer)
6184                         {
6185                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6186                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6187                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6188                         }
6189
6190                         // render reflected scene and copy into texture
6191                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6192                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6193                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6194                         r_refdef.view.clipplane = p->plane;
6195                         // reverse the cullface settings for this render
6196                         r_refdef.view.cullface_front = GL_FRONT;
6197                         r_refdef.view.cullface_back = GL_BACK;
6198                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6199                         {
6200                                 r_refdef.view.usecustompvs = true;
6201                                 if (p->pvsvalid)
6202                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6203                                 else
6204                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6205                         }
6206
6207                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6208                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6209                         R_ClearScreen(r_refdef.fogenabled);
6210                         if(r_water_scissormode.integer & 2)
6211                                 R_View_UpdateWithScissor(myscissor);
6212                         else
6213                                 R_View_Update();
6214                         R_AnimCache_CacheVisibleEntities();
6215                         if(r_water_scissormode.integer & 1)
6216                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6217                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6218
6219                         if (!p->fbo_reflection)
6220                                 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);
6221                         r_fb.water.hideplayer = false;
6222                 }
6223
6224                 // render the normal view scene and copy into texture
6225                 // (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)
6226                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6227                 {
6228                         r_refdef.view = myview;
6229                         if(r_water_scissormode.integer)
6230                         {
6231                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6232                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6233                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6234                         }
6235
6236                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6237
6238                         r_refdef.view.clipplane = p->plane;
6239                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6240                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6241
6242                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6243                         {
6244                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6245                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6246                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6247                                 R_RenderView_UpdateViewVectors();
6248                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6249                                 {
6250                                         r_refdef.view.usecustompvs = true;
6251                                         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);
6252                                 }
6253                         }
6254
6255                         PlaneClassify(&r_refdef.view.clipplane);
6256
6257                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6258                         R_ClearScreen(r_refdef.fogenabled);
6259                         if(r_water_scissormode.integer & 2)
6260                                 R_View_UpdateWithScissor(myscissor);
6261                         else
6262                                 R_View_Update();
6263                         R_AnimCache_CacheVisibleEntities();
6264                         if(r_water_scissormode.integer & 1)
6265                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6266                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6267
6268                         if (!p->fbo_refraction)
6269                                 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);
6270                         r_fb.water.hideplayer = false;
6271                 }
6272                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6273                 {
6274                         r_refdef.view = myview;
6275
6276                         r_refdef.view.clipplane = p->plane;
6277                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6278                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6279
6280                         r_refdef.view.width = r_fb.water.camerawidth;
6281                         r_refdef.view.height = r_fb.water.cameraheight;
6282                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6283                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6284                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6285                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6286
6287                         if(p->camera_entity)
6288                         {
6289                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6290                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6291                         }
6292
6293                         // note: all of the view is used for displaying... so
6294                         // there is no use in scissoring
6295
6296                         // reverse the cullface settings for this render
6297                         r_refdef.view.cullface_front = GL_FRONT;
6298                         r_refdef.view.cullface_back = GL_BACK;
6299                         // also reverse the view matrix
6300                         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
6301                         R_RenderView_UpdateViewVectors();
6302                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6303                         {
6304                                 r_refdef.view.usecustompvs = true;
6305                                 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);
6306                         }
6307                         
6308                         // camera needs no clipplane
6309                         r_refdef.view.useclipplane = false;
6310
6311                         PlaneClassify(&r_refdef.view.clipplane);
6312
6313                         r_fb.water.hideplayer = false;
6314
6315                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6316                         R_ClearScreen(r_refdef.fogenabled);
6317                         R_View_Update();
6318                         R_AnimCache_CacheVisibleEntities();
6319                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6320
6321                         if (!p->fbo_camera)
6322                                 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);
6323                         r_fb.water.hideplayer = false;
6324                 }
6325
6326         }
6327         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6328         r_fb.water.renderingscene = false;
6329         r_refdef.view = originalview;
6330         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6331         if (!r_fb.water.depthtexture)
6332                 R_ClearScreen(r_refdef.fogenabled);
6333         R_View_Update();
6334         R_AnimCache_CacheVisibleEntities();
6335         goto finish;
6336 error:
6337         r_refdef.view = originalview;
6338         r_fb.water.renderingscene = false;
6339         Cvar_SetValueQuick(&r_water, 0);
6340         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6341 finish:
6342         // lowquality hack, restore cvars
6343         if (qualityreduction > 0)
6344         {
6345                 if (qualityreduction >= 1)
6346                 {
6347                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6348                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6349                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6350                 }
6351                 if (qualityreduction >= 2)
6352                 {
6353                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6354                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6355                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6356                 }
6357         }
6358 }
6359
6360 static void R_Bloom_StartFrame(void)
6361 {
6362         int i;
6363         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6364         int viewwidth, viewheight;
6365         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6366         textype_t textype = TEXTYPE_COLORBUFFER;
6367
6368         switch (vid.renderpath)
6369         {
6370         case RENDERPATH_GL20:
6371                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6372                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6373                 {
6374                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6375                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6376                 }
6377                 break;
6378         case RENDERPATH_GL11:
6379         case RENDERPATH_GL13:
6380         case RENDERPATH_GLES1:
6381         case RENDERPATH_GLES2:
6382         case RENDERPATH_D3D9:
6383         case RENDERPATH_D3D10:
6384         case RENDERPATH_D3D11:
6385                 r_fb.usedepthtextures = false;
6386                 break;
6387         case RENDERPATH_SOFT:
6388                 r_fb.usedepthtextures = true;
6389                 break;
6390         }
6391
6392         if (r_viewscale_fpsscaling.integer)
6393         {
6394                 double actualframetime;
6395                 double targetframetime;
6396                 double adjust;
6397                 actualframetime = r_refdef.lastdrawscreentime;
6398                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6399                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6400                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6401                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6402                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6403                 viewscalefpsadjusted += adjust;
6404                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6405         }
6406         else
6407                 viewscalefpsadjusted = 1.0f;
6408
6409         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6410
6411         switch(vid.renderpath)
6412         {
6413         case RENDERPATH_GL20:
6414         case RENDERPATH_D3D9:
6415         case RENDERPATH_D3D10:
6416         case RENDERPATH_D3D11:
6417         case RENDERPATH_SOFT:
6418         case RENDERPATH_GLES2:
6419                 break;
6420         case RENDERPATH_GL11:
6421         case RENDERPATH_GL13:
6422         case RENDERPATH_GLES1:
6423                 return;
6424         }
6425
6426         // set bloomwidth and bloomheight to the bloom resolution that will be
6427         // used (often less than the screen resolution for faster rendering)
6428         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6429         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6430         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6431         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6432         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6433
6434         // calculate desired texture sizes
6435         if (vid.support.arb_texture_non_power_of_two)
6436         {
6437                 screentexturewidth = vid.width;
6438                 screentextureheight = vid.height;
6439                 bloomtexturewidth = r_fb.bloomwidth;
6440                 bloomtextureheight = r_fb.bloomheight;
6441         }
6442         else
6443         {
6444                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6445                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6446                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6447                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6448         }
6449
6450         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))
6451         {
6452                 Cvar_SetValueQuick(&r_bloom, 0);
6453                 Cvar_SetValueQuick(&r_motionblur, 0);
6454                 Cvar_SetValueQuick(&r_damageblur, 0);
6455         }
6456
6457         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6458          && !r_bloom.integer
6459          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6460          && !useviewfbo
6461          && r_viewscale.value == 1.0f
6462          && !r_viewscale_fpsscaling.integer)
6463                 screentexturewidth = screentextureheight = 0;
6464         if (!r_bloom.integer)
6465                 bloomtexturewidth = bloomtextureheight = 0;
6466
6467         // allocate textures as needed
6468         if (r_fb.screentexturewidth != screentexturewidth
6469          || r_fb.screentextureheight != screentextureheight
6470          || r_fb.bloomtexturewidth != bloomtexturewidth
6471          || r_fb.bloomtextureheight != bloomtextureheight
6472          || r_fb.textype != textype
6473          || useviewfbo != (r_fb.fbo != 0))
6474         {
6475                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6476                 {
6477                         if (r_fb.bloomtexture[i])
6478                                 R_FreeTexture(r_fb.bloomtexture[i]);
6479                         r_fb.bloomtexture[i] = NULL;
6480
6481                         if (r_fb.bloomfbo[i])
6482                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6483                         r_fb.bloomfbo[i] = 0;
6484                 }
6485
6486                 if (r_fb.fbo)
6487                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6488                 r_fb.fbo = 0;
6489
6490                 if (r_fb.colortexture)
6491                         R_FreeTexture(r_fb.colortexture);
6492                 r_fb.colortexture = NULL;
6493
6494                 if (r_fb.depthtexture)
6495                         R_FreeTexture(r_fb.depthtexture);
6496                 r_fb.depthtexture = NULL;
6497
6498                 if (r_fb.ghosttexture)
6499                         R_FreeTexture(r_fb.ghosttexture);
6500                 r_fb.ghosttexture = NULL;
6501
6502                 r_fb.screentexturewidth = screentexturewidth;
6503                 r_fb.screentextureheight = screentextureheight;
6504                 r_fb.bloomtexturewidth = bloomtexturewidth;
6505                 r_fb.bloomtextureheight = bloomtextureheight;
6506                 r_fb.textype = textype;
6507
6508                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6509                 {
6510                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6511                                 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);
6512                         r_fb.ghosttexture_valid = false;
6513                         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);
6514                         if (useviewfbo)
6515                         {
6516                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6517                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6518                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6519                         }
6520                 }
6521
6522                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6523                 {
6524                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6525                         {
6526                                 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);
6527                                 if (useviewfbo)
6528                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6529                         }
6530                 }
6531         }
6532
6533         // bloom texture is a different resolution
6534         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6535         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6536         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6537         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6538         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6539
6540         // set up a texcoord array for the full resolution screen image
6541         // (we have to keep this around to copy back during final render)
6542         r_fb.screentexcoord2f[0] = 0;
6543         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6544         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6545         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6546         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6547         r_fb.screentexcoord2f[5] = 0;
6548         r_fb.screentexcoord2f[6] = 0;
6549         r_fb.screentexcoord2f[7] = 0;
6550
6551         if(r_fb.fbo) 
6552         {
6553                 for (i = 1;i < 8;i += 2)
6554                 {
6555                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6556                 }
6557         }
6558
6559         // set up a texcoord array for the reduced resolution bloom image
6560         // (which will be additive blended over the screen image)
6561         r_fb.bloomtexcoord2f[0] = 0;
6562         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6563         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6564         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6565         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6566         r_fb.bloomtexcoord2f[5] = 0;
6567         r_fb.bloomtexcoord2f[6] = 0;
6568         r_fb.bloomtexcoord2f[7] = 0;
6569
6570         switch(vid.renderpath)
6571         {
6572         case RENDERPATH_GL11:
6573         case RENDERPATH_GL13:
6574         case RENDERPATH_GL20:
6575         case RENDERPATH_SOFT:
6576         case RENDERPATH_GLES1:
6577         case RENDERPATH_GLES2:
6578                 break;
6579         case RENDERPATH_D3D9:
6580         case RENDERPATH_D3D10:
6581         case RENDERPATH_D3D11:
6582                 for (i = 0;i < 4;i++)
6583                 {
6584                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6585                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6586                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6587                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6588                 }
6589                 break;
6590         }
6591
6592         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6593
6594         if (r_fb.fbo)
6595                 r_refdef.view.clear = true;
6596 }
6597
6598 static void R_Bloom_MakeTexture(void)
6599 {
6600         int x, range, dir;
6601         float xoffset, yoffset, r, brighten;
6602         rtexture_t *intex;
6603         float colorscale = r_bloom_colorscale.value;
6604
6605         r_refdef.stats[r_stat_bloom]++;
6606     
6607 #if 0
6608     // this copy is unnecessary since it happens in R_BlendView already
6609         if (!r_fb.fbo)
6610         {
6611                 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);
6612                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6613         }
6614 #endif
6615
6616         // scale down screen texture to the bloom texture size
6617         CHECKGLERROR
6618         r_fb.bloomindex = 0;
6619         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6620         R_SetViewport(&r_fb.bloomviewport);
6621         GL_DepthTest(false);
6622         GL_BlendFunc(GL_ONE, GL_ZERO);
6623         GL_Color(colorscale, colorscale, colorscale, 1);
6624         // 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...
6625         switch(vid.renderpath)
6626         {
6627         case RENDERPATH_GL11:
6628         case RENDERPATH_GL13:
6629         case RENDERPATH_GL20:
6630         case RENDERPATH_GLES1:
6631         case RENDERPATH_GLES2:
6632         case RENDERPATH_SOFT:
6633                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6634                 break;
6635         case RENDERPATH_D3D9:
6636         case RENDERPATH_D3D10:
6637         case RENDERPATH_D3D11:
6638                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6639                 break;
6640         }
6641         // TODO: do boxfilter scale-down in shader?
6642         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6643         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6644         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6645
6646         // we now have a properly scaled bloom image
6647         if (!r_fb.bloomfbo[r_fb.bloomindex])
6648         {
6649                 // copy it into the bloom texture
6650                 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);
6651                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6652         }
6653
6654         // multiply bloom image by itself as many times as desired
6655         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6656         {
6657                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6658                 r_fb.bloomindex ^= 1;
6659                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6660                 x *= 2;
6661                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6662                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6663                 {
6664                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6665                         GL_Color(r,r,r,1); // apply fix factor
6666                 }
6667                 else
6668                 {
6669                         if(x <= 2)
6670                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6671                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6672                         GL_Color(1,1,1,1); // no fix factor supported here
6673                 }
6674                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6675                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6676                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6677                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6678
6679                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6680                 {
6681                         // copy the darkened image to a texture
6682                         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);
6683                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6684                 }
6685         }
6686
6687         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6688         brighten = r_bloom_brighten.value;
6689         brighten = sqrt(brighten);
6690         if(range >= 1)
6691                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6692
6693         for (dir = 0;dir < 2;dir++)
6694         {
6695                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6696                 r_fb.bloomindex ^= 1;
6697                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6698                 // blend on at multiple vertical offsets to achieve a vertical blur
6699                 // TODO: do offset blends using GLSL
6700                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6701                 GL_BlendFunc(GL_ONE, GL_ZERO);
6702                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6703                 for (x = -range;x <= range;x++)
6704                 {
6705                         if (!dir){xoffset = 0;yoffset = x;}
6706                         else {xoffset = x;yoffset = 0;}
6707                         xoffset /= (float)r_fb.bloomtexturewidth;
6708                         yoffset /= (float)r_fb.bloomtextureheight;
6709                         // compute a texcoord array with the specified x and y offset
6710                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6711                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6712                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6713                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6714                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6715                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6716                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6717                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6718                         // this r value looks like a 'dot' particle, fading sharply to
6719                         // black at the edges
6720                         // (probably not realistic but looks good enough)
6721                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6722                         //r = brighten/(range*2+1);
6723                         r = brighten / (range * 2 + 1);
6724                         if(range >= 1)
6725                                 r *= (1 - x*x/(float)(range*range));
6726                         GL_Color(r, r, r, 1);
6727                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6728                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6729                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6730                         GL_BlendFunc(GL_ONE, GL_ONE);
6731                 }
6732
6733                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6734                 {
6735                         // copy the vertically or horizontally blurred bloom view to a texture
6736                         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);
6737                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6738                 }
6739         }
6740 }
6741
6742 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6743 {
6744         unsigned int permutation;
6745         float uservecs[4][4];
6746
6747         R_EntityMatrix(&identitymatrix);
6748
6749         switch (vid.renderpath)
6750         {
6751         case RENDERPATH_GL20:
6752         case RENDERPATH_D3D9:
6753         case RENDERPATH_D3D10:
6754         case RENDERPATH_D3D11:
6755         case RENDERPATH_SOFT:
6756         case RENDERPATH_GLES2:
6757                 permutation =
6758                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6759                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6760                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6761                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6762                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6763
6764                 if (r_fb.colortexture)
6765                 {
6766                         if (!r_fb.fbo)
6767                         {
6768                                 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);
6769                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6770                         }
6771
6772                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6773                         {
6774                                 // declare variables
6775                                 float blur_factor, blur_mouseaccel, blur_velocity;
6776                                 static float blur_average; 
6777                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6778
6779                                 // set a goal for the factoring
6780                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6781                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6782                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6783                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6784                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6785                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6786
6787                                 // from the goal, pick an averaged value between goal and last value
6788                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6789                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6790
6791                                 // enforce minimum amount of blur 
6792                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6793
6794                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6795
6796                                 // calculate values into a standard alpha
6797                                 cl.motionbluralpha = 1 - exp(-
6798                                                 (
6799                                                  (r_motionblur.value * blur_factor / 80)
6800                                                  +
6801                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6802                                                 )
6803                                                 /
6804                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6805                                           );
6806
6807                                 // randomization for the blur value to combat persistent ghosting
6808                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6809                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6810
6811                                 // apply the blur
6812                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6813                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6814                                 {
6815                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6816                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6817                                         switch(vid.renderpath)
6818                                         {
6819                                         case RENDERPATH_GL11:
6820                                         case RENDERPATH_GL13:
6821                                         case RENDERPATH_GL20:
6822                                         case RENDERPATH_GLES1:
6823                                         case RENDERPATH_GLES2:
6824                                         case RENDERPATH_SOFT:
6825                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6826                                                 break;
6827                                         case RENDERPATH_D3D9:
6828                                         case RENDERPATH_D3D10:
6829                                         case RENDERPATH_D3D11:
6830                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6831                                                 break;
6832                                         }
6833                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6834                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6835                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6836                                 }
6837
6838                                 // updates old view angles for next pass
6839                                 VectorCopy(cl.viewangles, blur_oldangles);
6840
6841                                 // copy view into the ghost texture
6842                                 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);
6843                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6844                                 r_fb.ghosttexture_valid = true;
6845                         }
6846                 }
6847                 else
6848                 {
6849                         // no r_fb.colortexture means we're rendering to the real fb
6850                         // we may still have to do view tint...
6851                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6852                         {
6853                                 // apply a color tint to the whole view
6854                                 R_ResetViewRendering2D(0, NULL, NULL);
6855                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6856                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6857                                 R_SetupShader_Generic_NoTexture(false, true);
6858                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6859                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6860                         }
6861                         break; // no screen processing, no bloom, skip it
6862                 }
6863
6864                 if (r_fb.bloomtexture[0])
6865                 {
6866                         // make the bloom texture
6867                         R_Bloom_MakeTexture();
6868                 }
6869
6870 #if _MSC_VER >= 1400
6871 #define sscanf sscanf_s
6872 #endif
6873                 memset(uservecs, 0, sizeof(uservecs));
6874                 if (r_glsl_postprocess_uservec1_enable.integer)
6875                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6876                 if (r_glsl_postprocess_uservec2_enable.integer)
6877                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6878                 if (r_glsl_postprocess_uservec3_enable.integer)
6879                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6880                 if (r_glsl_postprocess_uservec4_enable.integer)
6881                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6882
6883                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6884                 GL_Color(1, 1, 1, 1);
6885                 GL_BlendFunc(GL_ONE, GL_ZERO);
6886
6887                 switch(vid.renderpath)
6888                 {
6889                 case RENDERPATH_GL20:
6890                 case RENDERPATH_GLES2:
6891                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6892                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6893                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6894                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6895                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6896                         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]);
6897                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6898                         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]);
6899                         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]);
6900                         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]);
6901                         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]);
6902                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6903                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6904                         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);
6905                         break;
6906                 case RENDERPATH_D3D9:
6907 #ifdef SUPPORTD3D
6908                         // 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...
6909                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6910                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6911                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6912                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6913                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6914                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6915                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6916                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6917                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6918                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6919                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6920                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6921                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6922                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6923 #endif
6924                         break;
6925                 case RENDERPATH_D3D10:
6926                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6927                         break;
6928                 case RENDERPATH_D3D11:
6929                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6930                         break;
6931                 case RENDERPATH_SOFT:
6932                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6933                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6934                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6935                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6936                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6937                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6938                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6939                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6940                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6941                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6942                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6943                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6944                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6945                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6946                         break;
6947                 default:
6948                         break;
6949                 }
6950                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6951                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6952                 break;
6953         case RENDERPATH_GL11:
6954         case RENDERPATH_GL13:
6955         case RENDERPATH_GLES1:
6956                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6957                 {
6958                         // apply a color tint to the whole view
6959                         R_ResetViewRendering2D(0, NULL, NULL);
6960                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6961                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6962                         R_SetupShader_Generic_NoTexture(false, true);
6963                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6964                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6965                 }
6966                 break;
6967         }
6968 }
6969
6970 matrix4x4_t r_waterscrollmatrix;
6971
6972 void R_UpdateFog(void)
6973 {
6974         // Nehahra fog
6975         if (gamemode == GAME_NEHAHRA)
6976         {
6977                 if (gl_fogenable.integer)
6978                 {
6979                         r_refdef.oldgl_fogenable = true;
6980                         r_refdef.fog_density = gl_fogdensity.value;
6981                         r_refdef.fog_red = gl_fogred.value;
6982                         r_refdef.fog_green = gl_foggreen.value;
6983                         r_refdef.fog_blue = gl_fogblue.value;
6984                         r_refdef.fog_alpha = 1;
6985                         r_refdef.fog_start = 0;
6986                         r_refdef.fog_end = gl_skyclip.value;
6987                         r_refdef.fog_height = 1<<30;
6988                         r_refdef.fog_fadedepth = 128;
6989                 }
6990                 else if (r_refdef.oldgl_fogenable)
6991                 {
6992                         r_refdef.oldgl_fogenable = false;
6993                         r_refdef.fog_density = 0;
6994                         r_refdef.fog_red = 0;
6995                         r_refdef.fog_green = 0;
6996                         r_refdef.fog_blue = 0;
6997                         r_refdef.fog_alpha = 0;
6998                         r_refdef.fog_start = 0;
6999                         r_refdef.fog_end = 0;
7000                         r_refdef.fog_height = 1<<30;
7001                         r_refdef.fog_fadedepth = 128;
7002                 }
7003         }
7004
7005         // fog parms
7006         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7007         r_refdef.fog_start = max(0, r_refdef.fog_start);
7008         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7009
7010         if (r_refdef.fog_density && r_drawfog.integer)
7011         {
7012                 r_refdef.fogenabled = true;
7013                 // this is the point where the fog reaches 0.9986 alpha, which we
7014                 // consider a good enough cutoff point for the texture
7015                 // (0.9986 * 256 == 255.6)
7016                 if (r_fog_exp2.integer)
7017                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7018                 else
7019                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7020                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7021                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7022                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7023                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7024                         R_BuildFogHeightTexture();
7025                 // fog color was already set
7026                 // update the fog texture
7027                 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)
7028                         R_BuildFogTexture();
7029                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7030                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7031         }
7032         else
7033                 r_refdef.fogenabled = false;
7034
7035         // fog color
7036         if (r_refdef.fog_density)
7037         {
7038                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7039                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7040                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7041
7042                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7043                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7044                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7045                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7046
7047                 {
7048                         vec3_t fogvec;
7049                         VectorCopy(r_refdef.fogcolor, fogvec);
7050                         //   color.rgb *= ContrastBoost * SceneBrightness;
7051                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7052                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7053                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7054                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7055                 }
7056         }
7057 }
7058
7059 void R_UpdateVariables(void)
7060 {
7061         R_Textures_Frame();
7062
7063         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7064
7065         r_refdef.farclip = r_farclip_base.value;
7066         if (r_refdef.scene.worldmodel)
7067                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7068         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7069
7070         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7071                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7072         r_refdef.polygonfactor = 0;
7073         r_refdef.polygonoffset = 0;
7074         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7075         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7076
7077         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7078         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7079         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7080         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7081         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7082         if (FAKELIGHT_ENABLED)
7083         {
7084                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7085         }
7086         else if (r_refdef.scene.worldmodel)
7087         {
7088                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7089         }
7090         if (r_showsurfaces.integer)
7091         {
7092                 r_refdef.scene.rtworld = false;
7093                 r_refdef.scene.rtworldshadows = false;
7094                 r_refdef.scene.rtdlight = false;
7095                 r_refdef.scene.rtdlightshadows = false;
7096                 r_refdef.lightmapintensity = 0;
7097         }
7098
7099         r_gpuskeletal = false;
7100         switch(vid.renderpath)
7101         {
7102         case RENDERPATH_GL20:
7103                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7104         case RENDERPATH_D3D9:
7105         case RENDERPATH_D3D10:
7106         case RENDERPATH_D3D11:
7107         case RENDERPATH_SOFT:
7108         case RENDERPATH_GLES2:
7109                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7110                 {
7111                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7112                         {
7113                                 // build GLSL gamma texture
7114 #define RAMPWIDTH 256
7115                                 unsigned short ramp[RAMPWIDTH * 3];
7116                                 unsigned char rampbgr[RAMPWIDTH][4];
7117                                 int i;
7118
7119                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7120
7121                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7122                                 for(i = 0; i < RAMPWIDTH; ++i)
7123                                 {
7124                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7125                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7126                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7127                                         rampbgr[i][3] = 0;
7128                                 }
7129                                 if (r_texture_gammaramps)
7130                                 {
7131                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7132                                 }
7133                                 else
7134                                 {
7135                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7136                                 }
7137                         }
7138                 }
7139                 else
7140                 {
7141                         // remove GLSL gamma texture
7142                 }
7143                 break;
7144         case RENDERPATH_GL11:
7145         case RENDERPATH_GL13:
7146         case RENDERPATH_GLES1:
7147                 break;
7148         }
7149 }
7150
7151 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7152 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7153 /*
7154 ================
7155 R_SelectScene
7156 ================
7157 */
7158 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7159         if( scenetype != r_currentscenetype ) {
7160                 // store the old scenetype
7161                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7162                 r_currentscenetype = scenetype;
7163                 // move in the new scene
7164                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7165         }
7166 }
7167
7168 /*
7169 ================
7170 R_GetScenePointer
7171 ================
7172 */
7173 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7174 {
7175         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7176         if( scenetype == r_currentscenetype ) {
7177                 return &r_refdef.scene;
7178         } else {
7179                 return &r_scenes_store[ scenetype ];
7180         }
7181 }
7182
7183 static int R_SortEntities_Compare(const void *ap, const void *bp)
7184 {
7185         const entity_render_t *a = *(const entity_render_t **)ap;
7186         const entity_render_t *b = *(const entity_render_t **)bp;
7187
7188         // 1. compare model
7189         if(a->model < b->model)
7190                 return -1;
7191         if(a->model > b->model)
7192                 return +1;
7193
7194         // 2. compare skin
7195         // TODO possibly calculate the REAL skinnum here first using
7196         // skinscenes?
7197         if(a->skinnum < b->skinnum)
7198                 return -1;
7199         if(a->skinnum > b->skinnum)
7200                 return +1;
7201
7202         // everything we compared is equal
7203         return 0;
7204 }
7205 static void R_SortEntities(void)
7206 {
7207         // below or equal 2 ents, sorting never gains anything
7208         if(r_refdef.scene.numentities <= 2)
7209                 return;
7210         // sort
7211         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7212 }
7213
7214 /*
7215 ================
7216 R_RenderView
7217 ================
7218 */
7219 int dpsoftrast_test;
7220 extern cvar_t r_shadow_bouncegrid;
7221 void R_RenderView(void)
7222 {
7223         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7224         int fbo;
7225         rtexture_t *depthtexture;
7226         rtexture_t *colortexture;
7227
7228         dpsoftrast_test = r_test.integer;
7229
7230         if (r_timereport_active)
7231                 R_TimeReport("start");
7232         r_textureframe++; // used only by R_GetCurrentTexture
7233         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7234
7235         if(R_CompileShader_CheckStaticParms())
7236                 R_GLSL_Restart_f();
7237
7238         if (!r_drawentities.integer)
7239                 r_refdef.scene.numentities = 0;
7240         else if (r_sortentities.integer)
7241                 R_SortEntities();
7242
7243         R_AnimCache_ClearCache();
7244
7245         /* adjust for stereo display */
7246         if(R_Stereo_Active())
7247         {
7248                 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);
7249                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7250         }
7251
7252         if (r_refdef.view.isoverlay)
7253         {
7254                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7255                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7256                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7257                 R_TimeReport("depthclear");
7258
7259                 r_refdef.view.showdebug = false;
7260
7261                 r_fb.water.enabled = false;
7262                 r_fb.water.numwaterplanes = 0;
7263
7264                 R_RenderScene(0, NULL, NULL);
7265
7266                 r_refdef.view.matrix = originalmatrix;
7267
7268                 CHECKGLERROR
7269                 return;
7270         }
7271
7272         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7273         {
7274                 r_refdef.view.matrix = originalmatrix;
7275                 return;
7276         }
7277
7278         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7279
7280         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7281                 // in sRGB fallback, behave similar to true sRGB: convert this
7282                 // value from linear to sRGB
7283                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7284
7285         R_RenderView_UpdateViewVectors();
7286
7287         R_Shadow_UpdateWorldLightSelection();
7288
7289         R_Bloom_StartFrame();
7290
7291         // apply bloom brightness offset
7292         if(r_fb.bloomtexture[0])
7293                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7294
7295         R_Water_StartFrame();
7296
7297         // now we probably have an fbo to render into
7298         fbo = r_fb.fbo;
7299         depthtexture = r_fb.depthtexture;
7300         colortexture = r_fb.colortexture;
7301
7302         CHECKGLERROR
7303         if (r_timereport_active)
7304                 R_TimeReport("viewsetup");
7305
7306         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7307
7308         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7309         {
7310                 R_ClearScreen(r_refdef.fogenabled);
7311                 if (r_timereport_active)
7312                         R_TimeReport("viewclear");
7313         }
7314         r_refdef.view.clear = true;
7315
7316         r_refdef.view.showdebug = true;
7317
7318         R_View_Update();
7319         if (r_timereport_active)
7320                 R_TimeReport("visibility");
7321
7322         R_AnimCache_CacheVisibleEntities();
7323         if (r_timereport_active)
7324                 R_TimeReport("animcache");
7325
7326         R_Shadow_UpdateBounceGridTexture();
7327         if (r_timereport_active && r_shadow_bouncegrid.integer)
7328                 R_TimeReport("bouncegrid");
7329
7330         r_fb.water.numwaterplanes = 0;
7331         if (r_fb.water.enabled)
7332                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7333
7334         R_RenderScene(fbo, depthtexture, colortexture);
7335         r_fb.water.numwaterplanes = 0;
7336
7337         R_BlendView(fbo, depthtexture, colortexture);
7338         if (r_timereport_active)
7339                 R_TimeReport("blendview");
7340
7341         GL_Scissor(0, 0, vid.width, vid.height);
7342         GL_ScissorTest(false);
7343
7344         r_refdef.view.matrix = originalmatrix;
7345
7346         CHECKGLERROR
7347 }
7348
7349 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7350 {
7351         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7352         {
7353                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7354                 if (r_timereport_active)
7355                         R_TimeReport("waterworld");
7356         }
7357
7358         // don't let sound skip if going slow
7359         if (r_refdef.scene.extraupdate)
7360                 S_ExtraUpdate ();
7361
7362         R_DrawModelsAddWaterPlanes();
7363         if (r_timereport_active)
7364                 R_TimeReport("watermodels");
7365
7366         if (r_fb.water.numwaterplanes)
7367         {
7368                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7369                 if (r_timereport_active)
7370                         R_TimeReport("waterscenes");
7371         }
7372 }
7373
7374 extern cvar_t cl_locs_show;
7375 static void R_DrawLocs(void);
7376 static void R_DrawEntityBBoxes(void);
7377 static void R_DrawModelDecals(void);
7378 extern cvar_t cl_decals_newsystem;
7379 extern qboolean r_shadow_usingdeferredprepass;
7380 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7381 {
7382         qboolean shadowmapping = false;
7383
7384         if (r_timereport_active)
7385                 R_TimeReport("beginscene");
7386
7387         r_refdef.stats[r_stat_renders]++;
7388
7389         R_UpdateFog();
7390
7391         // don't let sound skip if going slow
7392         if (r_refdef.scene.extraupdate)
7393                 S_ExtraUpdate ();
7394
7395         R_MeshQueue_BeginScene();
7396
7397         R_SkyStartFrame();
7398
7399         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);
7400
7401         if (r_timereport_active)
7402                 R_TimeReport("skystartframe");
7403
7404         if (cl.csqc_vidvars.drawworld)
7405         {
7406                 // don't let sound skip if going slow
7407                 if (r_refdef.scene.extraupdate)
7408                         S_ExtraUpdate ();
7409
7410                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7411                 {
7412                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7413                         if (r_timereport_active)
7414                                 R_TimeReport("worldsky");
7415                 }
7416
7417                 if (R_DrawBrushModelsSky() && r_timereport_active)
7418                         R_TimeReport("bmodelsky");
7419
7420                 if (skyrendermasked && skyrenderlater)
7421                 {
7422                         // we have to force off the water clipping plane while rendering sky
7423                         R_SetupView(false, fbo, depthtexture, colortexture);
7424                         R_Sky();
7425                         R_SetupView(true, fbo, depthtexture, colortexture);
7426                         if (r_timereport_active)
7427                                 R_TimeReport("sky");
7428                 }
7429         }
7430
7431         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7432         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7433                 R_Shadow_PrepareModelShadows();
7434         if (r_timereport_active)
7435                 R_TimeReport("preparelights");
7436
7437         if (R_Shadow_ShadowMappingEnabled())
7438                 shadowmapping = true;
7439
7440         if (r_shadow_usingdeferredprepass)
7441                 R_Shadow_DrawPrepass();
7442
7443         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7444         {
7445                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7446                 if (r_timereport_active)
7447                         R_TimeReport("worlddepth");
7448         }
7449         if (r_depthfirst.integer >= 2)
7450         {
7451                 R_DrawModelsDepth();
7452                 if (r_timereport_active)
7453                         R_TimeReport("modeldepth");
7454         }
7455
7456         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7457         {
7458                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7459                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7460                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7461                 // don't let sound skip if going slow
7462                 if (r_refdef.scene.extraupdate)
7463                         S_ExtraUpdate ();
7464         }
7465
7466         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7467         {
7468                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7469                 if (r_timereport_active)
7470                         R_TimeReport("world");
7471         }
7472
7473         // don't let sound skip if going slow
7474         if (r_refdef.scene.extraupdate)
7475                 S_ExtraUpdate ();
7476
7477         R_DrawModels();
7478         if (r_timereport_active)
7479                 R_TimeReport("models");
7480
7481         // don't let sound skip if going slow
7482         if (r_refdef.scene.extraupdate)
7483                 S_ExtraUpdate ();
7484
7485         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7486         {
7487                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7488                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7489                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7490                 // don't let sound skip if going slow
7491                 if (r_refdef.scene.extraupdate)
7492                         S_ExtraUpdate ();
7493         }
7494
7495         if (!r_shadow_usingdeferredprepass)
7496         {
7497                 R_Shadow_DrawLights();
7498                 if (r_timereport_active)
7499                         R_TimeReport("rtlights");
7500         }
7501
7502         // don't let sound skip if going slow
7503         if (r_refdef.scene.extraupdate)
7504                 S_ExtraUpdate ();
7505
7506         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7507         {
7508                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7509                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7510                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7511                 // don't let sound skip if going slow
7512                 if (r_refdef.scene.extraupdate)
7513                         S_ExtraUpdate ();
7514         }
7515
7516         if (cl.csqc_vidvars.drawworld)
7517         {
7518                 if (cl_decals_newsystem.integer)
7519                 {
7520                         R_DrawModelDecals();
7521                         if (r_timereport_active)
7522                                 R_TimeReport("modeldecals");
7523                 }
7524                 else
7525                 {
7526                         R_DrawDecals();
7527                         if (r_timereport_active)
7528                                 R_TimeReport("decals");
7529                 }
7530
7531                 R_DrawParticles();
7532                 if (r_timereport_active)
7533                         R_TimeReport("particles");
7534
7535                 R_DrawExplosions();
7536                 if (r_timereport_active)
7537                         R_TimeReport("explosions");
7538
7539                 R_DrawLightningBeams();
7540                 if (r_timereport_active)
7541                         R_TimeReport("lightning");
7542         }
7543
7544         if (cl.csqc_loaded)
7545                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7546
7547         if (r_refdef.view.showdebug)
7548         {
7549                 if (cl_locs_show.integer)
7550                 {
7551                         R_DrawLocs();
7552                         if (r_timereport_active)
7553                                 R_TimeReport("showlocs");
7554                 }
7555
7556                 if (r_drawportals.integer)
7557                 {
7558                         R_DrawPortals();
7559                         if (r_timereport_active)
7560                                 R_TimeReport("portals");
7561                 }
7562
7563                 if (r_showbboxes.value > 0)
7564                 {
7565                         R_DrawEntityBBoxes();
7566                         if (r_timereport_active)
7567                                 R_TimeReport("bboxes");
7568                 }
7569         }
7570
7571         if (r_transparent.integer)
7572         {
7573                 R_MeshQueue_RenderTransparent();
7574                 if (r_timereport_active)
7575                         R_TimeReport("drawtrans");
7576         }
7577
7578         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))
7579         {
7580                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7581                 if (r_timereport_active)
7582                         R_TimeReport("worlddebug");
7583                 R_DrawModelsDebug();
7584                 if (r_timereport_active)
7585                         R_TimeReport("modeldebug");
7586         }
7587
7588         if (cl.csqc_vidvars.drawworld)
7589         {
7590                 R_Shadow_DrawCoronas();
7591                 if (r_timereport_active)
7592                         R_TimeReport("coronas");
7593         }
7594
7595 #if 0
7596         {
7597                 GL_DepthTest(false);
7598                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7599                 GL_Color(1, 1, 1, 1);
7600                 qglBegin(GL_POLYGON);
7601                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7602                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7603                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7604                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7605                 qglEnd();
7606                 qglBegin(GL_POLYGON);
7607                 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]);
7608                 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]);
7609                 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]);
7610                 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]);
7611                 qglEnd();
7612                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7613         }
7614 #endif
7615
7616         // don't let sound skip if going slow
7617         if (r_refdef.scene.extraupdate)
7618                 S_ExtraUpdate ();
7619 }
7620
7621 static const unsigned short bboxelements[36] =
7622 {
7623         5, 1, 3, 5, 3, 7,
7624         6, 2, 0, 6, 0, 4,
7625         7, 3, 2, 7, 2, 6,
7626         4, 0, 1, 4, 1, 5,
7627         4, 5, 7, 4, 7, 6,
7628         1, 0, 2, 1, 2, 3,
7629 };
7630
7631 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7632 {
7633         int i;
7634         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7635
7636         RSurf_ActiveWorldEntity();
7637
7638         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7639         GL_DepthMask(false);
7640         GL_DepthRange(0, 1);
7641         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7642 //      R_Mesh_ResetTextureState();
7643
7644         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7645         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7646         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7647         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7648         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7649         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7650         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7651         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7652         R_FillColors(color4f, 8, cr, cg, cb, ca);
7653         if (r_refdef.fogenabled)
7654         {
7655                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7656                 {
7657                         f1 = RSurf_FogVertex(v);
7658                         f2 = 1 - f1;
7659                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7660                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7661                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7662                 }
7663         }
7664         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7665         R_Mesh_ResetTextureState();
7666         R_SetupShader_Generic_NoTexture(false, false);
7667         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7668 }
7669
7670 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7671 {
7672         prvm_prog_t *prog = SVVM_prog;
7673         int i;
7674         float color[4];
7675         prvm_edict_t *edict;
7676
7677         // this function draws bounding boxes of server entities
7678         if (!sv.active)
7679                 return;
7680
7681         GL_CullFace(GL_NONE);
7682         R_SetupShader_Generic_NoTexture(false, false);
7683
7684         for (i = 0;i < numsurfaces;i++)
7685         {
7686                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7687                 switch ((int)PRVM_serveredictfloat(edict, solid))
7688                 {
7689                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7690                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7691                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7692                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7693                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7694                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7695                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7696                 }
7697                 color[3] *= r_showbboxes.value;
7698                 color[3] = bound(0, color[3], 1);
7699                 GL_DepthTest(!r_showdisabledepthtest.integer);
7700                 GL_CullFace(r_refdef.view.cullface_front);
7701                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7702         }
7703 }
7704
7705 static void R_DrawEntityBBoxes(void)
7706 {
7707         int i;
7708         prvm_edict_t *edict;
7709         vec3_t center;
7710         prvm_prog_t *prog = SVVM_prog;
7711
7712         // this function draws bounding boxes of server entities
7713         if (!sv.active)
7714                 return;
7715
7716         for (i = 0;i < prog->num_edicts;i++)
7717         {
7718                 edict = PRVM_EDICT_NUM(i);
7719                 if (edict->priv.server->free)
7720                         continue;
7721                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7722                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7723                         continue;
7724                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7725                         continue;
7726                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7727                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7728         }
7729 }
7730
7731 static const int nomodelelement3i[24] =
7732 {
7733         5, 2, 0,
7734         5, 1, 2,
7735         5, 0, 3,
7736         5, 3, 1,
7737         0, 2, 4,
7738         2, 1, 4,
7739         3, 0, 4,
7740         1, 3, 4
7741 };
7742
7743 static const unsigned short nomodelelement3s[24] =
7744 {
7745         5, 2, 0,
7746         5, 1, 2,
7747         5, 0, 3,
7748         5, 3, 1,
7749         0, 2, 4,
7750         2, 1, 4,
7751         3, 0, 4,
7752         1, 3, 4
7753 };
7754
7755 static const float nomodelvertex3f[6*3] =
7756 {
7757         -16,   0,   0,
7758          16,   0,   0,
7759           0, -16,   0,
7760           0,  16,   0,
7761           0,   0, -16,
7762           0,   0,  16
7763 };
7764
7765 static const float nomodelcolor4f[6*4] =
7766 {
7767         0.0f, 0.0f, 0.5f, 1.0f,
7768         0.0f, 0.0f, 0.5f, 1.0f,
7769         0.0f, 0.5f, 0.0f, 1.0f,
7770         0.0f, 0.5f, 0.0f, 1.0f,
7771         0.5f, 0.0f, 0.0f, 1.0f,
7772         0.5f, 0.0f, 0.0f, 1.0f
7773 };
7774
7775 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7776 {
7777         int i;
7778         float f1, f2, *c;
7779         float color4f[6*4];
7780
7781         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);
7782
7783         // this is only called once per entity so numsurfaces is always 1, and
7784         // surfacelist is always {0}, so this code does not handle batches
7785
7786         if (rsurface.ent_flags & RENDER_ADDITIVE)
7787         {
7788                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7789                 GL_DepthMask(false);
7790         }
7791         else if (rsurface.colormod[3] < 1)
7792         {
7793                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7794                 GL_DepthMask(false);
7795         }
7796         else
7797         {
7798                 GL_BlendFunc(GL_ONE, GL_ZERO);
7799                 GL_DepthMask(true);
7800         }
7801         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7802         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7803         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7804         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7805         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7806         for (i = 0, c = color4f;i < 6;i++, c += 4)
7807         {
7808                 c[0] *= rsurface.colormod[0];
7809                 c[1] *= rsurface.colormod[1];
7810                 c[2] *= rsurface.colormod[2];
7811                 c[3] *= rsurface.colormod[3];
7812         }
7813         if (r_refdef.fogenabled)
7814         {
7815                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7816                 {
7817                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7818                         f2 = 1 - f1;
7819                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7820                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7821                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7822                 }
7823         }
7824 //      R_Mesh_ResetTextureState();
7825         R_SetupShader_Generic_NoTexture(false, false);
7826         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7827         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7828 }
7829
7830 void R_DrawNoModel(entity_render_t *ent)
7831 {
7832         vec3_t org;
7833         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7834         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7835                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7836         else
7837                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7838 }
7839
7840 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7841 {
7842         vec3_t right1, right2, diff, normal;
7843
7844         VectorSubtract (org2, org1, normal);
7845
7846         // calculate 'right' vector for start
7847         VectorSubtract (r_refdef.view.origin, org1, diff);
7848         CrossProduct (normal, diff, right1);
7849         VectorNormalize (right1);
7850
7851         // calculate 'right' vector for end
7852         VectorSubtract (r_refdef.view.origin, org2, diff);
7853         CrossProduct (normal, diff, right2);
7854         VectorNormalize (right2);
7855
7856         vert[ 0] = org1[0] + width * right1[0];
7857         vert[ 1] = org1[1] + width * right1[1];
7858         vert[ 2] = org1[2] + width * right1[2];
7859         vert[ 3] = org1[0] - width * right1[0];
7860         vert[ 4] = org1[1] - width * right1[1];
7861         vert[ 5] = org1[2] - width * right1[2];
7862         vert[ 6] = org2[0] - width * right2[0];
7863         vert[ 7] = org2[1] - width * right2[1];
7864         vert[ 8] = org2[2] - width * right2[2];
7865         vert[ 9] = org2[0] + width * right2[0];
7866         vert[10] = org2[1] + width * right2[1];
7867         vert[11] = org2[2] + width * right2[2];
7868 }
7869
7870 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)
7871 {
7872         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7873         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7874         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7875         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7876         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7877         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7878         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7879         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7880         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7881         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7882         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7883         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7884 }
7885
7886 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7887 {
7888         int i;
7889         float *vertex3f;
7890         float v[3];
7891         VectorSet(v, x, y, z);
7892         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7893                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7894                         break;
7895         if (i == mesh->numvertices)
7896         {
7897                 if (mesh->numvertices < mesh->maxvertices)
7898                 {
7899                         VectorCopy(v, vertex3f);
7900                         mesh->numvertices++;
7901                 }
7902                 return mesh->numvertices;
7903         }
7904         else
7905                 return i;
7906 }
7907
7908 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7909 {
7910         int i;
7911         int *e, element[3];
7912         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7913         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7914         e = mesh->element3i + mesh->numtriangles * 3;
7915         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7916         {
7917                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7918                 if (mesh->numtriangles < mesh->maxtriangles)
7919                 {
7920                         *e++ = element[0];
7921                         *e++ = element[1];
7922                         *e++ = element[2];
7923                         mesh->numtriangles++;
7924                 }
7925                 element[1] = element[2];
7926         }
7927 }
7928
7929 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7930 {
7931         int i;
7932         int *e, element[3];
7933         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7934         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7935         e = mesh->element3i + mesh->numtriangles * 3;
7936         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7937         {
7938                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7939                 if (mesh->numtriangles < mesh->maxtriangles)
7940                 {
7941                         *e++ = element[0];
7942                         *e++ = element[1];
7943                         *e++ = element[2];
7944                         mesh->numtriangles++;
7945                 }
7946                 element[1] = element[2];
7947         }
7948 }
7949
7950 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7951 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7952 {
7953         int planenum, planenum2;
7954         int w;
7955         int tempnumpoints;
7956         mplane_t *plane, *plane2;
7957         double maxdist;
7958         double temppoints[2][256*3];
7959         // figure out how large a bounding box we need to properly compute this brush
7960         maxdist = 0;
7961         for (w = 0;w < numplanes;w++)
7962                 maxdist = max(maxdist, fabs(planes[w].dist));
7963         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7964         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7965         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7966         {
7967                 w = 0;
7968                 tempnumpoints = 4;
7969                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7970                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7971                 {
7972                         if (planenum2 == planenum)
7973                                 continue;
7974                         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);
7975                         w = !w;
7976                 }
7977                 if (tempnumpoints < 3)
7978                         continue;
7979                 // generate elements forming a triangle fan for this polygon
7980                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7981         }
7982 }
7983
7984 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)
7985 {
7986         texturelayer_t *layer;
7987         layer = t->currentlayers + t->currentnumlayers++;
7988         layer->type = type;
7989         layer->depthmask = depthmask;
7990         layer->blendfunc1 = blendfunc1;
7991         layer->blendfunc2 = blendfunc2;
7992         layer->texture = texture;
7993         layer->texmatrix = *matrix;
7994         layer->color[0] = r;
7995         layer->color[1] = g;
7996         layer->color[2] = b;
7997         layer->color[3] = a;
7998 }
7999
8000 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8001 {
8002         if(parms[0] == 0 && parms[1] == 0)
8003                 return false;
8004         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8005                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8006                         return false;
8007         return true;
8008 }
8009
8010 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8011 {
8012         double index, f;
8013         index = parms[2] + rsurface.shadertime * parms[3];
8014         index -= floor(index);
8015         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8016         {
8017         default:
8018         case Q3WAVEFUNC_NONE:
8019         case Q3WAVEFUNC_NOISE:
8020         case Q3WAVEFUNC_COUNT:
8021                 f = 0;
8022                 break;
8023         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8024         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8025         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8026         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8027         case Q3WAVEFUNC_TRIANGLE:
8028                 index *= 4;
8029                 f = index - floor(index);
8030                 if (index < 1)
8031                 {
8032                         // f = f;
8033                 }
8034                 else if (index < 2)
8035                         f = 1 - f;
8036                 else if (index < 3)
8037                         f = -f;
8038                 else
8039                         f = -(1 - f);
8040                 break;
8041         }
8042         f = parms[0] + parms[1] * f;
8043         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8044                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8045         return (float) f;
8046 }
8047
8048 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8049 {
8050         int w, h, idx;
8051         float shadertime;
8052         float f;
8053         float offsetd[2];
8054         float tcmat[12];
8055         matrix4x4_t matrix, temp;
8056         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8057         // it's better to have one huge fixup every 9 hours than gradual
8058         // degradation over time which looks consistently bad after many hours.
8059         //
8060         // tcmod scroll in particular suffers from this degradation which can't be
8061         // effectively worked around even with floor() tricks because we don't
8062         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8063         // a workaround involving floor() would be incorrect anyway...
8064         shadertime = rsurface.shadertime;
8065         if (shadertime >= 32768.0f)
8066                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8067         switch(tcmod->tcmod)
8068         {
8069                 case Q3TCMOD_COUNT:
8070                 case Q3TCMOD_NONE:
8071                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8072                                 matrix = r_waterscrollmatrix;
8073                         else
8074                                 matrix = identitymatrix;
8075                         break;
8076                 case Q3TCMOD_ENTITYTRANSLATE:
8077                         // this is used in Q3 to allow the gamecode to control texcoord
8078                         // scrolling on the entity, which is not supported in darkplaces yet.
8079                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8080                         break;
8081                 case Q3TCMOD_ROTATE:
8082                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8083                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8084                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8085                         break;
8086                 case Q3TCMOD_SCALE:
8087                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8088                         break;
8089                 case Q3TCMOD_SCROLL:
8090                         // this particular tcmod is a "bug for bug" compatible one with regards to
8091                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8092                         // specifically did the wrapping and so we must mimic that...
8093                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8094                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8095                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8096                         break;
8097                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8098                         w = (int) tcmod->parms[0];
8099                         h = (int) tcmod->parms[1];
8100                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8101                         f = f - floor(f);
8102                         idx = (int) floor(f * w * h);
8103                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8104                         break;
8105                 case Q3TCMOD_STRETCH:
8106                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8107                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8108                         break;
8109                 case Q3TCMOD_TRANSFORM:
8110                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8111                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8112                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8113                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8114                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8115                         break;
8116                 case Q3TCMOD_TURBULENT:
8117                         // this is handled in the RSurf_PrepareVertices function
8118                         matrix = identitymatrix;
8119                         break;
8120         }
8121         temp = *texmatrix;
8122         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8123 }
8124
8125 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8126 {
8127         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8128         char name[MAX_QPATH];
8129         skinframe_t *skinframe;
8130         unsigned char pixels[296*194];
8131         strlcpy(cache->name, skinname, sizeof(cache->name));
8132         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8133         if (developer_loading.integer)
8134                 Con_Printf("loading %s\n", name);
8135         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8136         if (!skinframe || !skinframe->base)
8137         {
8138                 unsigned char *f;
8139                 fs_offset_t filesize;
8140                 skinframe = NULL;
8141                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8142                 if (f)
8143                 {
8144                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8145                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8146                         Mem_Free(f);
8147                 }
8148         }
8149         cache->skinframe = skinframe;
8150 }
8151
8152 texture_t *R_GetCurrentTexture(texture_t *t)
8153 {
8154         int i;
8155         const entity_render_t *ent = rsurface.entity;
8156         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8157         q3shaderinfo_layer_tcmod_t *tcmod;
8158
8159         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8160                 return t->currentframe;
8161         t->update_lastrenderframe = r_textureframe;
8162         t->update_lastrenderentity = (void *)ent;
8163
8164         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8165                 t->camera_entity = ent->entitynumber;
8166         else
8167                 t->camera_entity = 0;
8168
8169         // switch to an alternate material if this is a q1bsp animated material
8170         {
8171                 texture_t *texture = t;
8172                 int s = rsurface.ent_skinnum;
8173                 if ((unsigned int)s >= (unsigned int)model->numskins)
8174                         s = 0;
8175                 if (model->skinscenes)
8176                 {
8177                         if (model->skinscenes[s].framecount > 1)
8178                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8179                         else
8180                                 s = model->skinscenes[s].firstframe;
8181                 }
8182                 if (s > 0)
8183                         t = t + s * model->num_surfaces;
8184                 if (t->animated)
8185                 {
8186                         // use an alternate animation if the entity's frame is not 0,
8187                         // and only if the texture has an alternate animation
8188                         if (t->animated == 2) // q2bsp
8189                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8190                         else if (rsurface.ent_alttextures && t->anim_total[1])
8191                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8192                         else
8193                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8194                 }
8195                 texture->currentframe = t;
8196         }
8197
8198         // update currentskinframe to be a qw skin or animation frame
8199         if (rsurface.ent_qwskin >= 0)
8200         {
8201                 i = rsurface.ent_qwskin;
8202                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8203                 {
8204                         r_qwskincache_size = cl.maxclients;
8205                         if (r_qwskincache)
8206                                 Mem_Free(r_qwskincache);
8207                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8208                 }
8209                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8210                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8211                 t->currentskinframe = r_qwskincache[i].skinframe;
8212                 if (t->currentskinframe == NULL)
8213                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8214         }
8215         else if (t->numskinframes >= 2)
8216                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8217         if (t->backgroundnumskinframes >= 2)
8218                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8219
8220         t->currentmaterialflags = t->basematerialflags;
8221         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8222         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8223                 t->currentalpha *= r_wateralpha.value;
8224         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8225                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8226         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8227                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8228         if (!(rsurface.ent_flags & RENDER_LIGHT))
8229                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8230         else if (FAKELIGHT_ENABLED)
8231         {
8232                 // no modellight if using fakelight for the map
8233         }
8234         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8235         {
8236                 // pick a model lighting mode
8237                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8238                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8239                 else
8240                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8241         }
8242         if (rsurface.ent_flags & RENDER_ADDITIVE)
8243                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8244         else if (t->currentalpha < 1)
8245                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8246         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8247         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8248                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8249         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8250                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8251         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8252                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8253         if (t->backgroundnumskinframes)
8254                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8255         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8256         {
8257                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8258                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8259         }
8260         else
8261                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8262         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8263         {
8264                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8265                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8266         }
8267         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8268                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8269
8270         // there is no tcmod
8271         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8272         {
8273                 t->currenttexmatrix = r_waterscrollmatrix;
8274                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8275         }
8276         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8277         {
8278                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8279                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8280         }
8281
8282         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8283                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8284         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8285                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8286
8287         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8288         if (t->currentskinframe->qpixels)
8289                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8290         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8291         if (!t->basetexture)
8292                 t->basetexture = r_texture_notexture;
8293         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8294         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8295         t->nmaptexture = t->currentskinframe->nmap;
8296         if (!t->nmaptexture)
8297                 t->nmaptexture = r_texture_blanknormalmap;
8298         t->glosstexture = r_texture_black;
8299         t->glowtexture = t->currentskinframe->glow;
8300         t->fogtexture = t->currentskinframe->fog;
8301         t->reflectmasktexture = t->currentskinframe->reflect;
8302         if (t->backgroundnumskinframes)
8303         {
8304                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8305                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8306                 t->backgroundglosstexture = r_texture_black;
8307                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8308                 if (!t->backgroundnmaptexture)
8309                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8310                 // make sure that if glow is going to be used, both textures are not NULL
8311                 if (!t->backgroundglowtexture && t->glowtexture)
8312                         t->backgroundglowtexture = r_texture_black;
8313                 if (!t->glowtexture && t->backgroundglowtexture)
8314                         t->glowtexture = r_texture_black;
8315         }
8316         else
8317         {
8318                 t->backgroundbasetexture = r_texture_white;
8319                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8320                 t->backgroundglosstexture = r_texture_black;
8321                 t->backgroundglowtexture = NULL;
8322         }
8323         t->specularpower = r_shadow_glossexponent.value;
8324         // TODO: store reference values for these in the texture?
8325         t->specularscale = 0;
8326         if (r_shadow_gloss.integer > 0)
8327         {
8328                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8329                 {
8330                         if (r_shadow_glossintensity.value > 0)
8331                         {
8332                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8333                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8334                                 t->specularscale = r_shadow_glossintensity.value;
8335                         }
8336                 }
8337                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8338                 {
8339                         t->glosstexture = r_texture_white;
8340                         t->backgroundglosstexture = r_texture_white;
8341                         t->specularscale = r_shadow_gloss2intensity.value;
8342                         t->specularpower = r_shadow_gloss2exponent.value;
8343                 }
8344         }
8345         t->specularscale *= t->specularscalemod;
8346         t->specularpower *= t->specularpowermod;
8347         t->rtlightambient = 0;
8348
8349         // lightmaps mode looks bad with dlights using actual texturing, so turn
8350         // off the colormap and glossmap, but leave the normalmap on as it still
8351         // accurately represents the shading involved
8352         if (gl_lightmaps.integer)
8353         {
8354                 t->basetexture = r_texture_grey128;
8355                 t->pantstexture = r_texture_black;
8356                 t->shirttexture = r_texture_black;
8357                 if (gl_lightmaps.integer < 2)
8358                         t->nmaptexture = r_texture_blanknormalmap;
8359                 t->glosstexture = r_texture_black;
8360                 t->glowtexture = NULL;
8361                 t->fogtexture = NULL;
8362                 t->reflectmasktexture = NULL;
8363                 t->backgroundbasetexture = NULL;
8364                 if (gl_lightmaps.integer < 2)
8365                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8366                 t->backgroundglosstexture = r_texture_black;
8367                 t->backgroundglowtexture = NULL;
8368                 t->specularscale = 0;
8369                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8370         }
8371
8372         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8373         VectorClear(t->dlightcolor);
8374         t->currentnumlayers = 0;
8375         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8376         {
8377                 int blendfunc1, blendfunc2;
8378                 qboolean depthmask;
8379                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8380                 {
8381                         blendfunc1 = GL_SRC_ALPHA;
8382                         blendfunc2 = GL_ONE;
8383                 }
8384                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8385                 {
8386                         blendfunc1 = GL_SRC_ALPHA;
8387                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8388                 }
8389                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8390                 {
8391                         blendfunc1 = t->customblendfunc[0];
8392                         blendfunc2 = t->customblendfunc[1];
8393                 }
8394                 else
8395                 {
8396                         blendfunc1 = GL_ONE;
8397                         blendfunc2 = GL_ZERO;
8398                 }
8399                 // don't colormod evilblend textures
8400                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8401                         VectorSet(t->lightmapcolor, 1, 1, 1);
8402                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8403                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8404                 {
8405                         // fullbright is not affected by r_refdef.lightmapintensity
8406                         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]);
8407                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8408                                 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]);
8409                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8410                                 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]);
8411                 }
8412                 else
8413                 {
8414                         vec3_t ambientcolor;
8415                         float colorscale;
8416                         // set the color tint used for lights affecting this surface
8417                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8418                         colorscale = 2;
8419                         // q3bsp has no lightmap updates, so the lightstylevalue that
8420                         // would normally be baked into the lightmap must be
8421                         // applied to the color
8422                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8423                         if (model->type == mod_brushq3)
8424                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8425                         colorscale *= r_refdef.lightmapintensity;
8426                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8427                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8428                         // basic lit geometry
8429                         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]);
8430                         // add pants/shirt if needed
8431                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8432                                 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]);
8433                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8434                                 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]);
8435                         // now add ambient passes if needed
8436                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8437                         {
8438                                 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]);
8439                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8440                                         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]);
8441                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8442                                         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]);
8443                         }
8444                 }
8445                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8446                         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]);
8447                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8448                 {
8449                         // if this is opaque use alpha blend which will darken the earlier
8450                         // passes cheaply.
8451                         //
8452                         // if this is an alpha blended material, all the earlier passes
8453                         // were darkened by fog already, so we only need to add the fog
8454                         // color ontop through the fog mask texture
8455                         //
8456                         // if this is an additive blended material, all the earlier passes
8457                         // were darkened by fog already, and we should not add fog color
8458                         // (because the background was not darkened, there is no fog color
8459                         // that was lost behind it).
8460                         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]);
8461                 }
8462         }
8463
8464         return t;
8465 }
8466
8467 rsurfacestate_t rsurface;
8468
8469 void RSurf_ActiveWorldEntity(void)
8470 {
8471         dp_model_t *model = r_refdef.scene.worldmodel;
8472         //if (rsurface.entity == r_refdef.scene.worldentity)
8473         //      return;
8474         rsurface.entity = r_refdef.scene.worldentity;
8475         rsurface.skeleton = NULL;
8476         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8477         rsurface.ent_skinnum = 0;
8478         rsurface.ent_qwskin = -1;
8479         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8480         rsurface.shadertime = r_refdef.scene.time;
8481         rsurface.matrix = identitymatrix;
8482         rsurface.inversematrix = identitymatrix;
8483         rsurface.matrixscale = 1;
8484         rsurface.inversematrixscale = 1;
8485         R_EntityMatrix(&identitymatrix);
8486         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8487         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8488         rsurface.fograngerecip = r_refdef.fograngerecip;
8489         rsurface.fogheightfade = r_refdef.fogheightfade;
8490         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8491         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8492         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8493         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8494         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8495         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8496         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8497         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8498         rsurface.colormod[3] = 1;
8499         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);
8500         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8501         rsurface.frameblend[0].lerp = 1;
8502         rsurface.ent_alttextures = false;
8503         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8504         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8505         rsurface.entityskeletaltransform3x4 = NULL;
8506         rsurface.entityskeletaltransform3x4buffer = NULL;
8507         rsurface.entityskeletaltransform3x4offset = 0;
8508         rsurface.entityskeletaltransform3x4size = 0;;
8509         rsurface.entityskeletalnumtransforms = 0;
8510         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8511         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8512         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8513         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8514         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8515         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8516         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8517         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8518         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8519         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8520         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8521         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8522         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8523         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8524         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8525         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8526         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8527         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8528         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8529         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8530         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8531         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8532         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8533         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8534         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8535         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8536         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8537         rsurface.modelelement3i = model->surfmesh.data_element3i;
8538         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8539         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8540         rsurface.modelelement3s = model->surfmesh.data_element3s;
8541         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8542         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8543         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8544         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8545         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8546         rsurface.modelsurfaces = model->data_surfaces;
8547         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8548         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8549         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8550         rsurface.modelgeneratedvertex = false;
8551         rsurface.batchgeneratedvertex = false;
8552         rsurface.batchfirstvertex = 0;
8553         rsurface.batchnumvertices = 0;
8554         rsurface.batchfirsttriangle = 0;
8555         rsurface.batchnumtriangles = 0;
8556         rsurface.batchvertex3f  = NULL;
8557         rsurface.batchvertex3f_vertexbuffer = NULL;
8558         rsurface.batchvertex3f_bufferoffset = 0;
8559         rsurface.batchsvector3f = NULL;
8560         rsurface.batchsvector3f_vertexbuffer = NULL;
8561         rsurface.batchsvector3f_bufferoffset = 0;
8562         rsurface.batchtvector3f = NULL;
8563         rsurface.batchtvector3f_vertexbuffer = NULL;
8564         rsurface.batchtvector3f_bufferoffset = 0;
8565         rsurface.batchnormal3f  = NULL;
8566         rsurface.batchnormal3f_vertexbuffer = NULL;
8567         rsurface.batchnormal3f_bufferoffset = 0;
8568         rsurface.batchlightmapcolor4f = NULL;
8569         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8570         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8571         rsurface.batchtexcoordtexture2f = NULL;
8572         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8573         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8574         rsurface.batchtexcoordlightmap2f = NULL;
8575         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8576         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8577         rsurface.batchskeletalindex4ub = NULL;
8578         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8579         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8580         rsurface.batchskeletalweight4ub = NULL;
8581         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8582         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8583         rsurface.batchvertexmesh = NULL;
8584         rsurface.batchvertexmesh_vertexbuffer = NULL;
8585         rsurface.batchvertexmesh_bufferoffset = 0;
8586         rsurface.batchelement3i = NULL;
8587         rsurface.batchelement3i_indexbuffer = NULL;
8588         rsurface.batchelement3i_bufferoffset = 0;
8589         rsurface.batchelement3s = NULL;
8590         rsurface.batchelement3s_indexbuffer = NULL;
8591         rsurface.batchelement3s_bufferoffset = 0;
8592         rsurface.passcolor4f = NULL;
8593         rsurface.passcolor4f_vertexbuffer = NULL;
8594         rsurface.passcolor4f_bufferoffset = 0;
8595         rsurface.forcecurrenttextureupdate = false;
8596 }
8597
8598 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8599 {
8600         dp_model_t *model = ent->model;
8601         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8602         //      return;
8603         rsurface.entity = (entity_render_t *)ent;
8604         rsurface.skeleton = ent->skeleton;
8605         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8606         rsurface.ent_skinnum = ent->skinnum;
8607         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;
8608         rsurface.ent_flags = ent->flags;
8609         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8610         rsurface.matrix = ent->matrix;
8611         rsurface.inversematrix = ent->inversematrix;
8612         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8613         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8614         R_EntityMatrix(&rsurface.matrix);
8615         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8616         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8617         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8618         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8619         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8620         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8621         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8622         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8623         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8624         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8625         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8626         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8627         rsurface.colormod[3] = ent->alpha;
8628         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8629         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8630         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8631         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8632         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8633         if (ent->model->brush.submodel && !prepass)
8634         {
8635                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8636                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8637         }
8638         // if the animcache code decided it should use the shader path, skip the deform step
8639         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8640         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8641         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8642         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8643         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8644         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8645         {
8646                 if (ent->animcache_vertex3f)
8647                 {
8648                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8649                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8650                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8651                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8652                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8653                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8654                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8655                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8656                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8657                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8658                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8659                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8660                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8661                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8662                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8663                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8664                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8665                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8666                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8667                 }
8668                 else if (wanttangents)
8669                 {
8670                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8671                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8672                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8673                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8674                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8675                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8676                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8677                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8678                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8679                         rsurface.modelvertexmesh = NULL;
8680                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8681                         rsurface.modelvertexmesh_bufferoffset = 0;
8682                         rsurface.modelvertex3f_vertexbuffer = NULL;
8683                         rsurface.modelvertex3f_bufferoffset = 0;
8684                         rsurface.modelvertex3f_vertexbuffer = 0;
8685                         rsurface.modelvertex3f_bufferoffset = 0;
8686                         rsurface.modelsvector3f_vertexbuffer = 0;
8687                         rsurface.modelsvector3f_bufferoffset = 0;
8688                         rsurface.modeltvector3f_vertexbuffer = 0;
8689                         rsurface.modeltvector3f_bufferoffset = 0;
8690                         rsurface.modelnormal3f_vertexbuffer = 0;
8691                         rsurface.modelnormal3f_bufferoffset = 0;
8692                 }
8693                 else if (wantnormals)
8694                 {
8695                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8696                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8697                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8698                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8699                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8700                         rsurface.modelsvector3f = NULL;
8701                         rsurface.modeltvector3f = NULL;
8702                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8703                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8704                         rsurface.modelvertexmesh = NULL;
8705                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8706                         rsurface.modelvertexmesh_bufferoffset = 0;
8707                         rsurface.modelvertex3f_vertexbuffer = NULL;
8708                         rsurface.modelvertex3f_bufferoffset = 0;
8709                         rsurface.modelvertex3f_vertexbuffer = 0;
8710                         rsurface.modelvertex3f_bufferoffset = 0;
8711                         rsurface.modelsvector3f_vertexbuffer = 0;
8712                         rsurface.modelsvector3f_bufferoffset = 0;
8713                         rsurface.modeltvector3f_vertexbuffer = 0;
8714                         rsurface.modeltvector3f_bufferoffset = 0;
8715                         rsurface.modelnormal3f_vertexbuffer = 0;
8716                         rsurface.modelnormal3f_bufferoffset = 0;
8717                 }
8718                 else
8719                 {
8720                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8721                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8722                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8723                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8724                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8725                         rsurface.modelsvector3f = NULL;
8726                         rsurface.modeltvector3f = NULL;
8727                         rsurface.modelnormal3f = NULL;
8728                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8729                         rsurface.modelvertexmesh = NULL;
8730                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8731                         rsurface.modelvertexmesh_bufferoffset = 0;
8732                         rsurface.modelvertex3f_vertexbuffer = NULL;
8733                         rsurface.modelvertex3f_bufferoffset = 0;
8734                         rsurface.modelvertex3f_vertexbuffer = 0;
8735                         rsurface.modelvertex3f_bufferoffset = 0;
8736                         rsurface.modelsvector3f_vertexbuffer = 0;
8737                         rsurface.modelsvector3f_bufferoffset = 0;
8738                         rsurface.modeltvector3f_vertexbuffer = 0;
8739                         rsurface.modeltvector3f_bufferoffset = 0;
8740                         rsurface.modelnormal3f_vertexbuffer = 0;
8741                         rsurface.modelnormal3f_bufferoffset = 0;
8742                 }
8743                 rsurface.modelgeneratedvertex = true;
8744         }
8745         else
8746         {
8747                 if (rsurface.entityskeletaltransform3x4)
8748                 {
8749                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8750                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8751                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8752                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8753                 }
8754                 else
8755                 {
8756                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8757                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8758                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8759                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8760                 }
8761                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8762                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8763                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8764                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8765                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8766                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8767                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8768                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8769                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8770                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8771                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8772                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8773                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8774                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8775                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8776                 rsurface.modelgeneratedvertex = false;
8777         }
8778         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8779         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8780         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8781         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8782         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8783         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8784         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8785         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8786         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8787         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8788         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8789         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8790         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8791         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8792         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8793         rsurface.modelelement3i = model->surfmesh.data_element3i;
8794         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8795         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8796         rsurface.modelelement3s = model->surfmesh.data_element3s;
8797         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8798         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8799         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8800         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8801         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8802         rsurface.modelsurfaces = model->data_surfaces;
8803         rsurface.batchgeneratedvertex = false;
8804         rsurface.batchfirstvertex = 0;
8805         rsurface.batchnumvertices = 0;
8806         rsurface.batchfirsttriangle = 0;
8807         rsurface.batchnumtriangles = 0;
8808         rsurface.batchvertex3f  = NULL;
8809         rsurface.batchvertex3f_vertexbuffer = NULL;
8810         rsurface.batchvertex3f_bufferoffset = 0;
8811         rsurface.batchsvector3f = NULL;
8812         rsurface.batchsvector3f_vertexbuffer = NULL;
8813         rsurface.batchsvector3f_bufferoffset = 0;
8814         rsurface.batchtvector3f = NULL;
8815         rsurface.batchtvector3f_vertexbuffer = NULL;
8816         rsurface.batchtvector3f_bufferoffset = 0;
8817         rsurface.batchnormal3f  = NULL;
8818         rsurface.batchnormal3f_vertexbuffer = NULL;
8819         rsurface.batchnormal3f_bufferoffset = 0;
8820         rsurface.batchlightmapcolor4f = NULL;
8821         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8822         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8823         rsurface.batchtexcoordtexture2f = NULL;
8824         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8825         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8826         rsurface.batchtexcoordlightmap2f = NULL;
8827         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8828         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8829         rsurface.batchskeletalindex4ub = NULL;
8830         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8831         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8832         rsurface.batchskeletalweight4ub = NULL;
8833         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8834         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8835         rsurface.batchvertexmesh = NULL;
8836         rsurface.batchvertexmesh_vertexbuffer = NULL;
8837         rsurface.batchvertexmesh_bufferoffset = 0;
8838         rsurface.batchelement3i = NULL;
8839         rsurface.batchelement3i_indexbuffer = NULL;
8840         rsurface.batchelement3i_bufferoffset = 0;
8841         rsurface.batchelement3s = NULL;
8842         rsurface.batchelement3s_indexbuffer = NULL;
8843         rsurface.batchelement3s_bufferoffset = 0;
8844         rsurface.passcolor4f = NULL;
8845         rsurface.passcolor4f_vertexbuffer = NULL;
8846         rsurface.passcolor4f_bufferoffset = 0;
8847         rsurface.forcecurrenttextureupdate = false;
8848 }
8849
8850 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)
8851 {
8852         rsurface.entity = r_refdef.scene.worldentity;
8853         rsurface.skeleton = NULL;
8854         rsurface.ent_skinnum = 0;
8855         rsurface.ent_qwskin = -1;
8856         rsurface.ent_flags = entflags;
8857         rsurface.shadertime = r_refdef.scene.time - shadertime;
8858         rsurface.modelnumvertices = numvertices;
8859         rsurface.modelnumtriangles = numtriangles;
8860         rsurface.matrix = *matrix;
8861         rsurface.inversematrix = *inversematrix;
8862         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8863         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8864         R_EntityMatrix(&rsurface.matrix);
8865         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8866         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8867         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8868         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8869         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8870         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8871         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8872         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8873         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8874         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8875         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8876         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8877         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);
8878         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8879         rsurface.frameblend[0].lerp = 1;
8880         rsurface.ent_alttextures = false;
8881         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8882         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8883         rsurface.entityskeletaltransform3x4 = NULL;
8884         rsurface.entityskeletaltransform3x4buffer = NULL;
8885         rsurface.entityskeletaltransform3x4offset = 0;
8886         rsurface.entityskeletaltransform3x4size = 0;
8887         rsurface.entityskeletalnumtransforms = 0;
8888         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8889         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8890         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8891         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8892         if (wanttangents)
8893         {
8894                 rsurface.modelvertex3f = (float *)vertex3f;
8895                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8896                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8897                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8898         }
8899         else if (wantnormals)
8900         {
8901                 rsurface.modelvertex3f = (float *)vertex3f;
8902                 rsurface.modelsvector3f = NULL;
8903                 rsurface.modeltvector3f = NULL;
8904                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8905         }
8906         else
8907         {
8908                 rsurface.modelvertex3f = (float *)vertex3f;
8909                 rsurface.modelsvector3f = NULL;
8910                 rsurface.modeltvector3f = NULL;
8911                 rsurface.modelnormal3f = NULL;
8912         }
8913         rsurface.modelvertexmesh = NULL;
8914         rsurface.modelvertexmesh_vertexbuffer = NULL;
8915         rsurface.modelvertexmesh_bufferoffset = 0;
8916         rsurface.modelvertex3f_vertexbuffer = 0;
8917         rsurface.modelvertex3f_bufferoffset = 0;
8918         rsurface.modelsvector3f_vertexbuffer = 0;
8919         rsurface.modelsvector3f_bufferoffset = 0;
8920         rsurface.modeltvector3f_vertexbuffer = 0;
8921         rsurface.modeltvector3f_bufferoffset = 0;
8922         rsurface.modelnormal3f_vertexbuffer = 0;
8923         rsurface.modelnormal3f_bufferoffset = 0;
8924         rsurface.modelgeneratedvertex = true;
8925         rsurface.modellightmapcolor4f  = (float *)color4f;
8926         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8927         rsurface.modellightmapcolor4f_bufferoffset = 0;
8928         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8929         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8930         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8931         rsurface.modeltexcoordlightmap2f  = NULL;
8932         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8933         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8934         rsurface.modelskeletalindex4ub = NULL;
8935         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8936         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8937         rsurface.modelskeletalweight4ub = NULL;
8938         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8939         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8940         rsurface.modelelement3i = (int *)element3i;
8941         rsurface.modelelement3i_indexbuffer = NULL;
8942         rsurface.modelelement3i_bufferoffset = 0;
8943         rsurface.modelelement3s = (unsigned short *)element3s;
8944         rsurface.modelelement3s_indexbuffer = NULL;
8945         rsurface.modelelement3s_bufferoffset = 0;
8946         rsurface.modellightmapoffsets = NULL;
8947         rsurface.modelsurfaces = NULL;
8948         rsurface.batchgeneratedvertex = false;
8949         rsurface.batchfirstvertex = 0;
8950         rsurface.batchnumvertices = 0;
8951         rsurface.batchfirsttriangle = 0;
8952         rsurface.batchnumtriangles = 0;
8953         rsurface.batchvertex3f  = NULL;
8954         rsurface.batchvertex3f_vertexbuffer = NULL;
8955         rsurface.batchvertex3f_bufferoffset = 0;
8956         rsurface.batchsvector3f = NULL;
8957         rsurface.batchsvector3f_vertexbuffer = NULL;
8958         rsurface.batchsvector3f_bufferoffset = 0;
8959         rsurface.batchtvector3f = NULL;
8960         rsurface.batchtvector3f_vertexbuffer = NULL;
8961         rsurface.batchtvector3f_bufferoffset = 0;
8962         rsurface.batchnormal3f  = NULL;
8963         rsurface.batchnormal3f_vertexbuffer = NULL;
8964         rsurface.batchnormal3f_bufferoffset = 0;
8965         rsurface.batchlightmapcolor4f = NULL;
8966         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8967         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8968         rsurface.batchtexcoordtexture2f = NULL;
8969         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8970         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8971         rsurface.batchtexcoordlightmap2f = NULL;
8972         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8973         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8974         rsurface.batchskeletalindex4ub = NULL;
8975         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8976         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8977         rsurface.batchskeletalweight4ub = NULL;
8978         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8979         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8980         rsurface.batchvertexmesh = NULL;
8981         rsurface.batchvertexmesh_vertexbuffer = NULL;
8982         rsurface.batchvertexmesh_bufferoffset = 0;
8983         rsurface.batchelement3i = NULL;
8984         rsurface.batchelement3i_indexbuffer = NULL;
8985         rsurface.batchelement3i_bufferoffset = 0;
8986         rsurface.batchelement3s = NULL;
8987         rsurface.batchelement3s_indexbuffer = NULL;
8988         rsurface.batchelement3s_bufferoffset = 0;
8989         rsurface.passcolor4f = NULL;
8990         rsurface.passcolor4f_vertexbuffer = NULL;
8991         rsurface.passcolor4f_bufferoffset = 0;
8992         rsurface.forcecurrenttextureupdate = true;
8993
8994         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8995         {
8996                 if ((wantnormals || wanttangents) && !normal3f)
8997                 {
8998                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8999                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9000                 }
9001                 if (wanttangents && !svector3f)
9002                 {
9003                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9004                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9005                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9006                 }
9007         }
9008 }
9009
9010 float RSurf_FogPoint(const float *v)
9011 {
9012         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9013         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9014         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9015         float FogHeightFade = r_refdef.fogheightfade;
9016         float fogfrac;
9017         unsigned int fogmasktableindex;
9018         if (r_refdef.fogplaneviewabove)
9019                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9020         else
9021                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9022         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9023         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9024 }
9025
9026 float RSurf_FogVertex(const float *v)
9027 {
9028         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9029         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9030         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9031         float FogHeightFade = rsurface.fogheightfade;
9032         float fogfrac;
9033         unsigned int fogmasktableindex;
9034         if (r_refdef.fogplaneviewabove)
9035                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9036         else
9037                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9038         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9039         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9040 }
9041
9042 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9043 {
9044         int i;
9045         for (i = 0;i < numelements;i++)
9046                 outelement3i[i] = inelement3i[i] + adjust;
9047 }
9048
9049 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9050 extern cvar_t gl_vbo;
9051 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9052 {
9053         int deformindex;
9054         int firsttriangle;
9055         int numtriangles;
9056         int firstvertex;
9057         int endvertex;
9058         int numvertices;
9059         int surfacefirsttriangle;
9060         int surfacenumtriangles;
9061         int surfacefirstvertex;
9062         int surfaceendvertex;
9063         int surfacenumvertices;
9064         int batchnumsurfaces = texturenumsurfaces;
9065         int batchnumvertices;
9066         int batchnumtriangles;
9067         int needsupdate;
9068         int i, j;
9069         qboolean gaps;
9070         qboolean dynamicvertex;
9071         float amplitude;
9072         float animpos;
9073         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9074         float waveparms[4];
9075         unsigned char *ub;
9076         q3shaderinfo_deform_t *deform;
9077         const msurface_t *surface, *firstsurface;
9078         r_vertexmesh_t *vertexmesh;
9079         if (!texturenumsurfaces)
9080                 return;
9081         // find vertex range of this surface batch
9082         gaps = false;
9083         firstsurface = texturesurfacelist[0];
9084         firsttriangle = firstsurface->num_firsttriangle;
9085         batchnumvertices = 0;
9086         batchnumtriangles = 0;
9087         firstvertex = endvertex = firstsurface->num_firstvertex;
9088         for (i = 0;i < texturenumsurfaces;i++)
9089         {
9090                 surface = texturesurfacelist[i];
9091                 if (surface != firstsurface + i)
9092                         gaps = true;
9093                 surfacefirstvertex = surface->num_firstvertex;
9094                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9095                 surfacenumvertices = surface->num_vertices;
9096                 surfacenumtriangles = surface->num_triangles;
9097                 if (firstvertex > surfacefirstvertex)
9098                         firstvertex = surfacefirstvertex;
9099                 if (endvertex < surfaceendvertex)
9100                         endvertex = surfaceendvertex;
9101                 batchnumvertices += surfacenumvertices;
9102                 batchnumtriangles += surfacenumtriangles;
9103         }
9104
9105         r_refdef.stats[r_stat_batch_batches]++;
9106         if (gaps)
9107                 r_refdef.stats[r_stat_batch_withgaps]++;
9108         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9109         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9110         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9111
9112         // we now know the vertex range used, and if there are any gaps in it
9113         rsurface.batchfirstvertex = firstvertex;
9114         rsurface.batchnumvertices = endvertex - firstvertex;
9115         rsurface.batchfirsttriangle = firsttriangle;
9116         rsurface.batchnumtriangles = batchnumtriangles;
9117
9118         // this variable holds flags for which properties have been updated that
9119         // may require regenerating vertexmesh array...
9120         needsupdate = 0;
9121
9122         // check if any dynamic vertex processing must occur
9123         dynamicvertex = false;
9124
9125         // a cvar to force the dynamic vertex path to be taken, for debugging
9126         if (r_batch_debugdynamicvertexpath.integer)
9127         {
9128                 if (!dynamicvertex)
9129                 {
9130                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9131                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9132                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9133                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9134                 }
9135                 dynamicvertex = true;
9136         }
9137
9138         // if there is a chance of animated vertex colors, it's a dynamic batch
9139         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9140         {
9141                 if (!dynamicvertex)
9142                 {
9143                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9144                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9145                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9146                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9147                 }
9148                 dynamicvertex = true;
9149                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9150         }
9151
9152         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9153         {
9154                 switch (deform->deform)
9155                 {
9156                 default:
9157                 case Q3DEFORM_PROJECTIONSHADOW:
9158                 case Q3DEFORM_TEXT0:
9159                 case Q3DEFORM_TEXT1:
9160                 case Q3DEFORM_TEXT2:
9161                 case Q3DEFORM_TEXT3:
9162                 case Q3DEFORM_TEXT4:
9163                 case Q3DEFORM_TEXT5:
9164                 case Q3DEFORM_TEXT6:
9165                 case Q3DEFORM_TEXT7:
9166                 case Q3DEFORM_NONE:
9167                         break;
9168                 case Q3DEFORM_AUTOSPRITE:
9169                         if (!dynamicvertex)
9170                         {
9171                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9172                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9173                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9174                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9175                         }
9176                         dynamicvertex = true;
9177                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9178                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9179                         break;
9180                 case Q3DEFORM_AUTOSPRITE2:
9181                         if (!dynamicvertex)
9182                         {
9183                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9184                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9185                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9186                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9187                         }
9188                         dynamicvertex = true;
9189                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9190                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9191                         break;
9192                 case Q3DEFORM_NORMAL:
9193                         if (!dynamicvertex)
9194                         {
9195                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9196                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9197                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9198                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9199                         }
9200                         dynamicvertex = true;
9201                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9202                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9203                         break;
9204                 case Q3DEFORM_WAVE:
9205                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9206                                 break; // if wavefunc is a nop, ignore this transform
9207                         if (!dynamicvertex)
9208                         {
9209                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9210                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9211                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9212                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9213                         }
9214                         dynamicvertex = true;
9215                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9216                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9217                         break;
9218                 case Q3DEFORM_BULGE:
9219                         if (!dynamicvertex)
9220                         {
9221                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9222                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9223                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9224                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9225                         }
9226                         dynamicvertex = true;
9227                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9228                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9229                         break;
9230                 case Q3DEFORM_MOVE:
9231                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9232                                 break; // if wavefunc is a nop, ignore this transform
9233                         if (!dynamicvertex)
9234                         {
9235                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9236                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9237                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9238                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9239                         }
9240                         dynamicvertex = true;
9241                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9242                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9243                         break;
9244                 }
9245         }
9246         switch(rsurface.texture->tcgen.tcgen)
9247         {
9248         default:
9249         case Q3TCGEN_TEXTURE:
9250                 break;
9251         case Q3TCGEN_LIGHTMAP:
9252                 if (!dynamicvertex)
9253                 {
9254                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9255                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9256                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9257                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9258                 }
9259                 dynamicvertex = true;
9260                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9261                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9262                 break;
9263         case Q3TCGEN_VECTOR:
9264                 if (!dynamicvertex)
9265                 {
9266                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9267                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9268                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9269                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9270                 }
9271                 dynamicvertex = true;
9272                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9273                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9274                 break;
9275         case Q3TCGEN_ENVIRONMENT:
9276                 if (!dynamicvertex)
9277                 {
9278                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9279                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9280                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9281                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9282                 }
9283                 dynamicvertex = true;
9284                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9285                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9286                 break;
9287         }
9288         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9289         {
9290                 if (!dynamicvertex)
9291                 {
9292                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9293                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9294                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9295                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9296                 }
9297                 dynamicvertex = true;
9298                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9299                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9300         }
9301
9302         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9303         {
9304                 if (!dynamicvertex)
9305                 {
9306                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9307                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9308                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9309                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9310                 }
9311                 dynamicvertex = true;
9312                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9313         }
9314
9315         // when the model data has no vertex buffer (dynamic mesh), we need to
9316         // eliminate gaps
9317         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9318                 batchneed |= BATCHNEED_NOGAPS;
9319
9320         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9321         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9322         // we ensure this by treating the vertex batch as dynamic...
9323         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9324         {
9325                 if (!dynamicvertex)
9326                 {
9327                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9328                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9329                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9330                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9331                 }
9332                 dynamicvertex = true;
9333         }
9334
9335         if (dynamicvertex)
9336         {
9337                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9338                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9339                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9340                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9341                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9342                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9343                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9344                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9345         }
9346
9347         // if needsupdate, we have to do a dynamic vertex batch for sure
9348         if (needsupdate & batchneed)
9349         {
9350                 if (!dynamicvertex)
9351                 {
9352                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9353                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9354                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9355                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9356                 }
9357                 dynamicvertex = true;
9358         }
9359
9360         // see if we need to build vertexmesh from arrays
9361         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9362         {
9363                 if (!dynamicvertex)
9364                 {
9365                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9366                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9367                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9368                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9369                 }
9370                 dynamicvertex = true;
9371         }
9372
9373         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9374         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9375                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9376
9377         rsurface.batchvertex3f = rsurface.modelvertex3f;
9378         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9379         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9380         rsurface.batchsvector3f = rsurface.modelsvector3f;
9381         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9382         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9383         rsurface.batchtvector3f = rsurface.modeltvector3f;
9384         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9385         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9386         rsurface.batchnormal3f = rsurface.modelnormal3f;
9387         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9388         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9389         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9390         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9391         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9392         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9393         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9394         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9395         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9396         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9397         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9398         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9399         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9400         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9401         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9402         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9403         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9404         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9405         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9406         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9407         rsurface.batchelement3i = rsurface.modelelement3i;
9408         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9409         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9410         rsurface.batchelement3s = rsurface.modelelement3s;
9411         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9412         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9413         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9414         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9415         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9416         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9417         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9418
9419         // if any dynamic vertex processing has to occur in software, we copy the
9420         // entire surface list together before processing to rebase the vertices
9421         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9422         //
9423         // if any gaps exist and we do not have a static vertex buffer, we have to
9424         // copy the surface list together to avoid wasting upload bandwidth on the
9425         // vertices in the gaps.
9426         //
9427         // if gaps exist and we have a static vertex buffer, we can choose whether
9428         // to combine the index buffer ranges into one dynamic index buffer or
9429         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9430         //
9431         // in many cases the batch is reduced to one draw call.
9432
9433         rsurface.batchmultidraw = false;
9434         rsurface.batchmultidrawnumsurfaces = 0;
9435         rsurface.batchmultidrawsurfacelist = NULL;
9436
9437         if (!dynamicvertex)
9438         {
9439                 // static vertex data, just set pointers...
9440                 rsurface.batchgeneratedvertex = false;
9441                 // if there are gaps, we want to build a combined index buffer,
9442                 // otherwise use the original static buffer with an appropriate offset
9443                 if (gaps)
9444                 {
9445                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9446                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9447                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9448                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9449                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9450                         {
9451                                 rsurface.batchmultidraw = true;
9452                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9453                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9454                                 return;
9455                         }
9456                         // build a new triangle elements array for this batch
9457                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9458                         rsurface.batchfirsttriangle = 0;
9459                         numtriangles = 0;
9460                         for (i = 0;i < texturenumsurfaces;i++)
9461                         {
9462                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9463                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9464                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9465                                 numtriangles += surfacenumtriangles;
9466                         }
9467                         rsurface.batchelement3i_indexbuffer = NULL;
9468                         rsurface.batchelement3i_bufferoffset = 0;
9469                         rsurface.batchelement3s = NULL;
9470                         rsurface.batchelement3s_indexbuffer = NULL;
9471                         rsurface.batchelement3s_bufferoffset = 0;
9472                         if (endvertex <= 65536)
9473                         {
9474                                 // make a 16bit (unsigned short) index array if possible
9475                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9476                                 for (i = 0;i < numtriangles*3;i++)
9477                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9478                         }
9479                         // upload buffer data for the copytriangles batch
9480                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9481                         {
9482                                 if (rsurface.batchelement3s)
9483                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9484                                 else if (rsurface.batchelement3i)
9485                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9486                         }
9487                 }
9488                 else
9489                 {
9490                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9491                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9492                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9493                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9494                 }
9495                 return;
9496         }
9497
9498         // something needs software processing, do it for real...
9499         // we only directly handle separate array data in this case and then
9500         // generate interleaved data if needed...
9501         rsurface.batchgeneratedvertex = true;
9502         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9503         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9504         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9505         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9506
9507         // now copy the vertex data into a combined array and make an index array
9508         // (this is what Quake3 does all the time)
9509         // we also apply any skeletal animation here that would have been done in
9510         // the vertex shader, because most of the dynamic vertex animation cases
9511         // need actual vertex positions and normals
9512         //if (dynamicvertex)
9513         {
9514                 rsurface.batchvertexmesh = NULL;
9515                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9516                 rsurface.batchvertexmesh_bufferoffset = 0;
9517                 rsurface.batchvertex3f = NULL;
9518                 rsurface.batchvertex3f_vertexbuffer = NULL;
9519                 rsurface.batchvertex3f_bufferoffset = 0;
9520                 rsurface.batchsvector3f = NULL;
9521                 rsurface.batchsvector3f_vertexbuffer = NULL;
9522                 rsurface.batchsvector3f_bufferoffset = 0;
9523                 rsurface.batchtvector3f = NULL;
9524                 rsurface.batchtvector3f_vertexbuffer = NULL;
9525                 rsurface.batchtvector3f_bufferoffset = 0;
9526                 rsurface.batchnormal3f = NULL;
9527                 rsurface.batchnormal3f_vertexbuffer = NULL;
9528                 rsurface.batchnormal3f_bufferoffset = 0;
9529                 rsurface.batchlightmapcolor4f = NULL;
9530                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9531                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9532                 rsurface.batchtexcoordtexture2f = NULL;
9533                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9534                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9535                 rsurface.batchtexcoordlightmap2f = NULL;
9536                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9537                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9538                 rsurface.batchskeletalindex4ub = NULL;
9539                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9540                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9541                 rsurface.batchskeletalweight4ub = NULL;
9542                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9543                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9544                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9545                 rsurface.batchelement3i_indexbuffer = NULL;
9546                 rsurface.batchelement3i_bufferoffset = 0;
9547                 rsurface.batchelement3s = NULL;
9548                 rsurface.batchelement3s_indexbuffer = NULL;
9549                 rsurface.batchelement3s_bufferoffset = 0;
9550                 rsurface.batchskeletaltransform3x4buffer = NULL;
9551                 rsurface.batchskeletaltransform3x4offset = 0;
9552                 rsurface.batchskeletaltransform3x4size = 0;
9553                 // we'll only be setting up certain arrays as needed
9554                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9555                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9556                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9557                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9558                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9559                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9560                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9561                 {
9562                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9563                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9564                 }
9565                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9566                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9567                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9568                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9569                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9570                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9571                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9572                 {
9573                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9574                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9575                 }
9576                 numvertices = 0;
9577                 numtriangles = 0;
9578                 for (i = 0;i < texturenumsurfaces;i++)
9579                 {
9580                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9581                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9582                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9583                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9584                         // copy only the data requested
9585                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9586                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9587                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9588                         {
9589                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9590                                 {
9591                                         if (rsurface.batchvertex3f)
9592                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9593                                         else
9594                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9595                                 }
9596                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9597                                 {
9598                                         if (rsurface.modelnormal3f)
9599                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9600                                         else
9601                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9602                                 }
9603                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9604                                 {
9605                                         if (rsurface.modelsvector3f)
9606                                         {
9607                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9608                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9609                                         }
9610                                         else
9611                                         {
9612                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9613                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9614                                         }
9615                                 }
9616                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9617                                 {
9618                                         if (rsurface.modellightmapcolor4f)
9619                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9620                                         else
9621                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9622                                 }
9623                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9624                                 {
9625                                         if (rsurface.modeltexcoordtexture2f)
9626                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9627                                         else
9628                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9629                                 }
9630                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9631                                 {
9632                                         if (rsurface.modeltexcoordlightmap2f)
9633                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9634                                         else
9635                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9636                                 }
9637                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9638                                 {
9639                                         if (rsurface.modelskeletalindex4ub)
9640                                         {
9641                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9642                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9643                                         }
9644                                         else
9645                                         {
9646                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9647                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9648                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9649                                                 for (j = 0;j < surfacenumvertices;j++)
9650                                                         ub[j*4] = 255;
9651                                         }
9652                                 }
9653                         }
9654                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9655                         numvertices += surfacenumvertices;
9656                         numtriangles += surfacenumtriangles;
9657                 }
9658
9659                 // generate a 16bit index array as well if possible
9660                 // (in general, dynamic batches fit)
9661                 if (numvertices <= 65536)
9662                 {
9663                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9664                         for (i = 0;i < numtriangles*3;i++)
9665                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9666                 }
9667
9668                 // since we've copied everything, the batch now starts at 0
9669                 rsurface.batchfirstvertex = 0;
9670                 rsurface.batchnumvertices = batchnumvertices;
9671                 rsurface.batchfirsttriangle = 0;
9672                 rsurface.batchnumtriangles = batchnumtriangles;
9673         }
9674
9675         // apply skeletal animation that would have been done in the vertex shader
9676         if (rsurface.batchskeletaltransform3x4)
9677         {
9678                 const unsigned char *si;
9679                 const unsigned char *sw;
9680                 const float *t[4];
9681                 const float *b = rsurface.batchskeletaltransform3x4;
9682                 float *vp, *vs, *vt, *vn;
9683                 float w[4];
9684                 float m[3][4], n[3][4];
9685                 float tp[3], ts[3], tt[3], tn[3];
9686                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9687                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9688                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9689                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9690                 si = rsurface.batchskeletalindex4ub;
9691                 sw = rsurface.batchskeletalweight4ub;
9692                 vp = rsurface.batchvertex3f;
9693                 vs = rsurface.batchsvector3f;
9694                 vt = rsurface.batchtvector3f;
9695                 vn = rsurface.batchnormal3f;
9696                 memset(m[0], 0, sizeof(m));
9697                 memset(n[0], 0, sizeof(n));
9698                 for (i = 0;i < batchnumvertices;i++)
9699                 {
9700                         t[0] = b + si[0]*12;
9701                         if (sw[0] == 255)
9702                         {
9703                                 // common case - only one matrix
9704                                 m[0][0] = t[0][ 0];
9705                                 m[0][1] = t[0][ 1];
9706                                 m[0][2] = t[0][ 2];
9707                                 m[0][3] = t[0][ 3];
9708                                 m[1][0] = t[0][ 4];
9709                                 m[1][1] = t[0][ 5];
9710                                 m[1][2] = t[0][ 6];
9711                                 m[1][3] = t[0][ 7];
9712                                 m[2][0] = t[0][ 8];
9713                                 m[2][1] = t[0][ 9];
9714                                 m[2][2] = t[0][10];
9715                                 m[2][3] = t[0][11];
9716                         }
9717                         else if (sw[2] + sw[3])
9718                         {
9719                                 // blend 4 matrices
9720                                 t[1] = b + si[1]*12;
9721                                 t[2] = b + si[2]*12;
9722                                 t[3] = b + si[3]*12;
9723                                 w[0] = sw[0] * (1.0f / 255.0f);
9724                                 w[1] = sw[1] * (1.0f / 255.0f);
9725                                 w[2] = sw[2] * (1.0f / 255.0f);
9726                                 w[3] = sw[3] * (1.0f / 255.0f);
9727                                 // blend the matrices
9728                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9729                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9730                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9731                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9732                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9733                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9734                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9735                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9736                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9737                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9738                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9739                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9740                         }
9741                         else
9742                         {
9743                                 // blend 2 matrices
9744                                 t[1] = b + si[1]*12;
9745                                 w[0] = sw[0] * (1.0f / 255.0f);
9746                                 w[1] = sw[1] * (1.0f / 255.0f);
9747                                 // blend the matrices
9748                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9749                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9750                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9751                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9752                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9753                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9754                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9755                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9756                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9757                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9758                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9759                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9760                         }
9761                         si += 4;
9762                         sw += 4;
9763                         // modify the vertex
9764                         VectorCopy(vp, tp);
9765                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9766                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9767                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9768                         vp += 3;
9769                         if (vn)
9770                         {
9771                                 // the normal transformation matrix is a set of cross products...
9772                                 CrossProduct(m[1], m[2], n[0]);
9773                                 CrossProduct(m[2], m[0], n[1]);
9774                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9775                                 VectorCopy(vn, tn);
9776                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9777                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9778                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9779                                 VectorNormalize(vn);
9780                                 vn += 3;
9781                                 if (vs)
9782                                 {
9783                                         VectorCopy(vs, ts);
9784                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9785                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9786                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9787                                         VectorNormalize(vs);
9788                                         vs += 3;
9789                                         VectorCopy(vt, tt);
9790                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9791                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9792                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9793                                         VectorNormalize(vt);
9794                                         vt += 3;
9795                                 }
9796                         }
9797                 }
9798                 rsurface.batchskeletaltransform3x4 = NULL;
9799                 rsurface.batchskeletalnumtransforms = 0;
9800         }
9801
9802         // q1bsp surfaces rendered in vertex color mode have to have colors
9803         // calculated based on lightstyles
9804         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9805         {
9806                 // generate color arrays for the surfaces in this list
9807                 int c[4];
9808                 int scale;
9809                 int size3;
9810                 const int *offsets;
9811                 const unsigned char *lm;
9812                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9813                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9814                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9815                 numvertices = 0;
9816                 for (i = 0;i < texturenumsurfaces;i++)
9817                 {
9818                         surface = texturesurfacelist[i];
9819                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9820                         surfacenumvertices = surface->num_vertices;
9821                         if (surface->lightmapinfo->samples)
9822                         {
9823                                 for (j = 0;j < surfacenumvertices;j++)
9824                                 {
9825                                         lm = surface->lightmapinfo->samples + offsets[j];
9826                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9827                                         VectorScale(lm, scale, c);
9828                                         if (surface->lightmapinfo->styles[1] != 255)
9829                                         {
9830                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9831                                                 lm += size3;
9832                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9833                                                 VectorMA(c, scale, lm, c);
9834                                                 if (surface->lightmapinfo->styles[2] != 255)
9835                                                 {
9836                                                         lm += size3;
9837                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9838                                                         VectorMA(c, scale, lm, c);
9839                                                         if (surface->lightmapinfo->styles[3] != 255)
9840                                                         {
9841                                                                 lm += size3;
9842                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9843                                                                 VectorMA(c, scale, lm, c);
9844                                                         }
9845                                                 }
9846                                         }
9847                                         c[0] >>= 7;
9848                                         c[1] >>= 7;
9849                                         c[2] >>= 7;
9850                                         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);
9851                                         numvertices++;
9852                                 }
9853                         }
9854                         else
9855                         {
9856                                 for (j = 0;j < surfacenumvertices;j++)
9857                                 {
9858                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9859                                         numvertices++;
9860                                 }
9861                         }
9862                 }
9863         }
9864
9865         // if vertices are deformed (sprite flares and things in maps, possibly
9866         // water waves, bulges and other deformations), modify the copied vertices
9867         // in place
9868         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9869         {
9870                 float scale;
9871                 switch (deform->deform)
9872                 {
9873                 default:
9874                 case Q3DEFORM_PROJECTIONSHADOW:
9875                 case Q3DEFORM_TEXT0:
9876                 case Q3DEFORM_TEXT1:
9877                 case Q3DEFORM_TEXT2:
9878                 case Q3DEFORM_TEXT3:
9879                 case Q3DEFORM_TEXT4:
9880                 case Q3DEFORM_TEXT5:
9881                 case Q3DEFORM_TEXT6:
9882                 case Q3DEFORM_TEXT7:
9883                 case Q3DEFORM_NONE:
9884                         break;
9885                 case Q3DEFORM_AUTOSPRITE:
9886                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9887                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9888                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9889                         VectorNormalize(newforward);
9890                         VectorNormalize(newright);
9891                         VectorNormalize(newup);
9892 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9893 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9894 //                      rsurface.batchvertex3f_bufferoffset = 0;
9895 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9896 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9897 //                      rsurface.batchsvector3f_bufferoffset = 0;
9898 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9899 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9900 //                      rsurface.batchtvector3f_bufferoffset = 0;
9901 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9902 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9903 //                      rsurface.batchnormal3f_bufferoffset = 0;
9904                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9905                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9906                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9907                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9908                                 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);
9909                         // a single autosprite surface can contain multiple sprites...
9910                         for (j = 0;j < batchnumvertices - 3;j += 4)
9911                         {
9912                                 VectorClear(center);
9913                                 for (i = 0;i < 4;i++)
9914                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9915                                 VectorScale(center, 0.25f, center);
9916                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9917                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9918                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9919                                 for (i = 0;i < 4;i++)
9920                                 {
9921                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9922                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9923                                 }
9924                         }
9925                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9926                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9927                         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);
9928                         break;
9929                 case Q3DEFORM_AUTOSPRITE2:
9930                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9931                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9932                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9933                         VectorNormalize(newforward);
9934                         VectorNormalize(newright);
9935                         VectorNormalize(newup);
9936 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9937 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9938 //                      rsurface.batchvertex3f_bufferoffset = 0;
9939                         {
9940                                 const float *v1, *v2;
9941                                 vec3_t start, end;
9942                                 float f, l;
9943                                 struct
9944                                 {
9945                                         float length2;
9946                                         const float *v1;
9947                                         const float *v2;
9948                                 }
9949                                 shortest[2];
9950                                 memset(shortest, 0, sizeof(shortest));
9951                                 // a single autosprite surface can contain multiple sprites...
9952                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9953                                 {
9954                                         VectorClear(center);
9955                                         for (i = 0;i < 4;i++)
9956                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9957                                         VectorScale(center, 0.25f, center);
9958                                         // find the two shortest edges, then use them to define the
9959                                         // axis vectors for rotating around the central axis
9960                                         for (i = 0;i < 6;i++)
9961                                         {
9962                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9963                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9964                                                 l = VectorDistance2(v1, v2);
9965                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9966                                                 if (v1[2] != v2[2])
9967                                                         l += (1.0f / 1024.0f);
9968                                                 if (shortest[0].length2 > l || i == 0)
9969                                                 {
9970                                                         shortest[1] = shortest[0];
9971                                                         shortest[0].length2 = l;
9972                                                         shortest[0].v1 = v1;
9973                                                         shortest[0].v2 = v2;
9974                                                 }
9975                                                 else if (shortest[1].length2 > l || i == 1)
9976                                                 {
9977                                                         shortest[1].length2 = l;
9978                                                         shortest[1].v1 = v1;
9979                                                         shortest[1].v2 = v2;
9980                                                 }
9981                                         }
9982                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9983                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9984                                         // this calculates the right vector from the shortest edge
9985                                         // and the up vector from the edge midpoints
9986                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9987                                         VectorNormalize(right);
9988                                         VectorSubtract(end, start, up);
9989                                         VectorNormalize(up);
9990                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9991                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9992                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9993                                         VectorNegate(forward, forward);
9994                                         VectorReflect(forward, 0, up, forward);
9995                                         VectorNormalize(forward);
9996                                         CrossProduct(up, forward, newright);
9997                                         VectorNormalize(newright);
9998                                         // rotate the quad around the up axis vector, this is made
9999                                         // especially easy by the fact we know the quad is flat,
10000                                         // so we only have to subtract the center position and
10001                                         // measure distance along the right vector, and then
10002                                         // multiply that by the newright vector and add back the
10003                                         // center position
10004                                         // we also need to subtract the old position to undo the
10005                                         // displacement from the center, which we do with a
10006                                         // DotProduct, the subtraction/addition of center is also
10007                                         // optimized into DotProducts here
10008                                         l = DotProduct(right, center);
10009                                         for (i = 0;i < 4;i++)
10010                                         {
10011                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10012                                                 f = DotProduct(right, v1) - l;
10013                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10014                                         }
10015                                 }
10016                         }
10017                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10018                         {
10019 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10020 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10021 //                              rsurface.batchnormal3f_bufferoffset = 0;
10022                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10023                         }
10024                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10025                         {
10026 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10027 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10028 //                              rsurface.batchsvector3f_bufferoffset = 0;
10029 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10030 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10031 //                              rsurface.batchtvector3f_bufferoffset = 0;
10032                                 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);
10033                         }
10034                         break;
10035                 case Q3DEFORM_NORMAL:
10036                         // deform the normals to make reflections wavey
10037                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10038                         rsurface.batchnormal3f_vertexbuffer = NULL;
10039                         rsurface.batchnormal3f_bufferoffset = 0;
10040                         for (j = 0;j < batchnumvertices;j++)
10041                         {
10042                                 float vertex[3];
10043                                 float *normal = rsurface.batchnormal3f + 3*j;
10044                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10045                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10046                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10047                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10048                                 VectorNormalize(normal);
10049                         }
10050                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10051                         {
10052 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10053 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10054 //                              rsurface.batchsvector3f_bufferoffset = 0;
10055 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10056 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10057 //                              rsurface.batchtvector3f_bufferoffset = 0;
10058                                 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);
10059                         }
10060                         break;
10061                 case Q3DEFORM_WAVE:
10062                         // deform vertex array to make wavey water and flags and such
10063                         waveparms[0] = deform->waveparms[0];
10064                         waveparms[1] = deform->waveparms[1];
10065                         waveparms[2] = deform->waveparms[2];
10066                         waveparms[3] = deform->waveparms[3];
10067                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10068                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10069                         // this is how a divisor of vertex influence on deformation
10070                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10071                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10072 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10073 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10074 //                      rsurface.batchvertex3f_bufferoffset = 0;
10075 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10076 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10077 //                      rsurface.batchnormal3f_bufferoffset = 0;
10078                         for (j = 0;j < batchnumvertices;j++)
10079                         {
10080                                 // if the wavefunc depends on time, evaluate it per-vertex
10081                                 if (waveparms[3])
10082                                 {
10083                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10084                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10085                                 }
10086                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10087                         }
10088                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10089                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10090                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10091                         {
10092 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10093 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10094 //                              rsurface.batchsvector3f_bufferoffset = 0;
10095 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10096 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10097 //                              rsurface.batchtvector3f_bufferoffset = 0;
10098                                 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);
10099                         }
10100                         break;
10101                 case Q3DEFORM_BULGE:
10102                         // deform vertex array to make the surface have moving bulges
10103 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10104 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10105 //                      rsurface.batchvertex3f_bufferoffset = 0;
10106 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10107 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10108 //                      rsurface.batchnormal3f_bufferoffset = 0;
10109                         for (j = 0;j < batchnumvertices;j++)
10110                         {
10111                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10112                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10113                         }
10114                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10115                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10116                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10117                         {
10118 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10119 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10120 //                              rsurface.batchsvector3f_bufferoffset = 0;
10121 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10122 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10123 //                              rsurface.batchtvector3f_bufferoffset = 0;
10124                                 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);
10125                         }
10126                         break;
10127                 case Q3DEFORM_MOVE:
10128                         // deform vertex array
10129                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10130                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10131                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10132                         VectorScale(deform->parms, scale, waveparms);
10133 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10134 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10135 //                      rsurface.batchvertex3f_bufferoffset = 0;
10136                         for (j = 0;j < batchnumvertices;j++)
10137                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10138                         break;
10139                 }
10140         }
10141
10142         if (rsurface.batchtexcoordtexture2f)
10143         {
10144         // generate texcoords based on the chosen texcoord source
10145                 switch(rsurface.texture->tcgen.tcgen)
10146                 {
10147                 default:
10148                 case Q3TCGEN_TEXTURE:
10149                         break;
10150                 case Q3TCGEN_LIGHTMAP:
10151         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10152         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10153         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10154                         if (rsurface.batchtexcoordlightmap2f)
10155                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10156                         break;
10157                 case Q3TCGEN_VECTOR:
10158         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10159         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10160         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10161                         for (j = 0;j < batchnumvertices;j++)
10162                         {
10163                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10164                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10165                         }
10166                         break;
10167                 case Q3TCGEN_ENVIRONMENT:
10168                         // make environment reflections using a spheremap
10169                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10170                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10171                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10172                         for (j = 0;j < batchnumvertices;j++)
10173                         {
10174                                 // identical to Q3A's method, but executed in worldspace so
10175                                 // carried models can be shiny too
10176
10177                                 float viewer[3], d, reflected[3], worldreflected[3];
10178
10179                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10180                                 // VectorNormalize(viewer);
10181
10182                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10183
10184                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10185                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10186                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10187                                 // note: this is proportinal to viewer, so we can normalize later
10188
10189                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10190                                 VectorNormalize(worldreflected);
10191
10192                                 // note: this sphere map only uses world x and z!
10193                                 // so positive and negative y will LOOK THE SAME.
10194                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10195                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10196                         }
10197                         break;
10198                 }
10199                 // the only tcmod that needs software vertex processing is turbulent, so
10200                 // check for it here and apply the changes if needed
10201                 // and we only support that as the first one
10202                 // (handling a mixture of turbulent and other tcmods would be problematic
10203                 //  without punting it entirely to a software path)
10204                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10205                 {
10206                         amplitude = rsurface.texture->tcmods[0].parms[1];
10207                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10208         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10209         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10210         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10211                         for (j = 0;j < batchnumvertices;j++)
10212                         {
10213                                 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);
10214                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10215                         }
10216                 }
10217         }
10218
10219         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10220         {
10221                 // convert the modified arrays to vertex structs
10222 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10223 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10224 //              rsurface.batchvertexmesh_bufferoffset = 0;
10225                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10226                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10227                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10228                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10229                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10230                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10231                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10232                 {
10233                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10234                         {
10235                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10236                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10237                         }
10238                 }
10239                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10240                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10241                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10242                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10243                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10244                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10245                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10246                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10247                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10248                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10249                 {
10250                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10251                         {
10252                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10253                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10254                         }
10255                 }
10256         }
10257
10258         // upload buffer data for the dynamic batch
10259         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10260         {
10261                 if (rsurface.batchvertexmesh)
10262                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10263                 else
10264                 {
10265                         if (rsurface.batchvertex3f)
10266                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10267                         if (rsurface.batchsvector3f)
10268                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10269                         if (rsurface.batchtvector3f)
10270                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10271                         if (rsurface.batchnormal3f)
10272                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10273                         if (rsurface.batchlightmapcolor4f)
10274                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10275                         if (rsurface.batchtexcoordtexture2f)
10276                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10277                         if (rsurface.batchtexcoordlightmap2f)
10278                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10279                         if (rsurface.batchskeletalindex4ub)
10280                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10281                         if (rsurface.batchskeletalweight4ub)
10282                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10283                 }
10284                 if (rsurface.batchelement3s)
10285                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10286                 else if (rsurface.batchelement3i)
10287                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10288         }
10289 }
10290
10291 void RSurf_DrawBatch(void)
10292 {
10293         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10294         // through the pipeline, killing it earlier in the pipeline would have
10295         // per-surface overhead rather than per-batch overhead, so it's best to
10296         // reject it here, before it hits glDraw.
10297         if (rsurface.batchnumtriangles == 0)
10298                 return;
10299 #if 0
10300         // batch debugging code
10301         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10302         {
10303                 int i;
10304                 int j;
10305                 int c;
10306                 const int *e;
10307                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10308                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10309                 {
10310                         c = e[i];
10311                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10312                         {
10313                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10314                                 {
10315                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10316                                                 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);
10317                                         break;
10318                                 }
10319                         }
10320                 }
10321         }
10322 #endif
10323         if (rsurface.batchmultidraw)
10324         {
10325                 // issue multiple draws rather than copying index data
10326                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10327                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10328                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10329                 for (i = 0;i < numsurfaces;)
10330                 {
10331                         // combine consecutive surfaces as one draw
10332                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10333                                 if (surfacelist[j] != surfacelist[k] + 1)
10334                                         break;
10335                         firstvertex = surfacelist[i]->num_firstvertex;
10336                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10337                         firsttriangle = surfacelist[i]->num_firsttriangle;
10338                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10339                         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);
10340                         i = j;
10341                 }
10342         }
10343         else
10344         {
10345                 // there is only one consecutive run of index data (may have been combined)
10346                 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);
10347         }
10348 }
10349
10350 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10351 {
10352         // pick the closest matching water plane
10353         int planeindex, vertexindex, bestplaneindex = -1;
10354         float d, bestd;
10355         vec3_t vert;
10356         const float *v;
10357         r_waterstate_waterplane_t *p;
10358         qboolean prepared = false;
10359         bestd = 0;
10360         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10361         {
10362                 if(p->camera_entity != rsurface.texture->camera_entity)
10363                         continue;
10364                 d = 0;
10365                 if(!prepared)
10366                 {
10367                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10368                         prepared = true;
10369                         if(rsurface.batchnumvertices == 0)
10370                                 break;
10371                 }
10372                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10373                 {
10374                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10375                         d += fabs(PlaneDiff(vert, &p->plane));
10376                 }
10377                 if (bestd > d || bestplaneindex < 0)
10378                 {
10379                         bestd = d;
10380                         bestplaneindex = planeindex;
10381                 }
10382         }
10383         return bestplaneindex;
10384         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10385         // this situation though, as it might be better to render single larger
10386         // batches with useless stuff (backface culled for example) than to
10387         // render multiple smaller batches
10388 }
10389
10390 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10391 {
10392         int i;
10393         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10394         rsurface.passcolor4f_vertexbuffer = 0;
10395         rsurface.passcolor4f_bufferoffset = 0;
10396         for (i = 0;i < rsurface.batchnumvertices;i++)
10397                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10398 }
10399
10400 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10401 {
10402         int i;
10403         float f;
10404         const float *v;
10405         const float *c;
10406         float *c2;
10407         if (rsurface.passcolor4f)
10408         {
10409                 // generate color arrays
10410                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10411                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10412                 rsurface.passcolor4f_vertexbuffer = 0;
10413                 rsurface.passcolor4f_bufferoffset = 0;
10414                 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)
10415                 {
10416                         f = RSurf_FogVertex(v);
10417                         c2[0] = c[0] * f;
10418                         c2[1] = c[1] * f;
10419                         c2[2] = c[2] * f;
10420                         c2[3] = c[3];
10421                 }
10422         }
10423         else
10424         {
10425                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10426                 rsurface.passcolor4f_vertexbuffer = 0;
10427                 rsurface.passcolor4f_bufferoffset = 0;
10428                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10429                 {
10430                         f = RSurf_FogVertex(v);
10431                         c2[0] = f;
10432                         c2[1] = f;
10433                         c2[2] = f;
10434                         c2[3] = 1;
10435                 }
10436         }
10437 }
10438
10439 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10440 {
10441         int i;
10442         float f;
10443         const float *v;
10444         const float *c;
10445         float *c2;
10446         if (!rsurface.passcolor4f)
10447                 return;
10448         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10449         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10450         rsurface.passcolor4f_vertexbuffer = 0;
10451         rsurface.passcolor4f_bufferoffset = 0;
10452         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)
10453         {
10454                 f = RSurf_FogVertex(v);
10455                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10456                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10457                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10458                 c2[3] = c[3];
10459         }
10460 }
10461
10462 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10463 {
10464         int i;
10465         const float *c;
10466         float *c2;
10467         if (!rsurface.passcolor4f)
10468                 return;
10469         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10470         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10471         rsurface.passcolor4f_vertexbuffer = 0;
10472         rsurface.passcolor4f_bufferoffset = 0;
10473         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10474         {
10475                 c2[0] = c[0] * r;
10476                 c2[1] = c[1] * g;
10477                 c2[2] = c[2] * b;
10478                 c2[3] = c[3] * a;
10479         }
10480 }
10481
10482 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10483 {
10484         int i;
10485         const float *c;
10486         float *c2;
10487         if (!rsurface.passcolor4f)
10488                 return;
10489         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10490         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10491         rsurface.passcolor4f_vertexbuffer = 0;
10492         rsurface.passcolor4f_bufferoffset = 0;
10493         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10494         {
10495                 c2[0] = c[0] + r_refdef.scene.ambient;
10496                 c2[1] = c[1] + r_refdef.scene.ambient;
10497                 c2[2] = c[2] + r_refdef.scene.ambient;
10498                 c2[3] = c[3];
10499         }
10500 }
10501
10502 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10503 {
10504         // TODO: optimize
10505         rsurface.passcolor4f = NULL;
10506         rsurface.passcolor4f_vertexbuffer = 0;
10507         rsurface.passcolor4f_bufferoffset = 0;
10508         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10509         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10510         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10511         GL_Color(r, g, b, a);
10512         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10513         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10514         R_Mesh_TexMatrix(0, NULL);
10515         RSurf_DrawBatch();
10516 }
10517
10518 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10519 {
10520         // TODO: optimize applyfog && applycolor case
10521         // just apply fog if necessary, and tint the fog color array if necessary
10522         rsurface.passcolor4f = NULL;
10523         rsurface.passcolor4f_vertexbuffer = 0;
10524         rsurface.passcolor4f_bufferoffset = 0;
10525         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10526         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10527         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10528         GL_Color(r, g, b, a);
10529         RSurf_DrawBatch();
10530 }
10531
10532 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10533 {
10534         // TODO: optimize
10535         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10536         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10537         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10538         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10539         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10540         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10541         GL_Color(r, g, b, a);
10542         RSurf_DrawBatch();
10543 }
10544
10545 static void RSurf_DrawBatch_GL11_ClampColor(void)
10546 {
10547         int i;
10548         const float *c1;
10549         float *c2;
10550         if (!rsurface.passcolor4f)
10551                 return;
10552         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10553         {
10554                 c2[0] = bound(0.0f, c1[0], 1.0f);
10555                 c2[1] = bound(0.0f, c1[1], 1.0f);
10556                 c2[2] = bound(0.0f, c1[2], 1.0f);
10557                 c2[3] = bound(0.0f, c1[3], 1.0f);
10558         }
10559 }
10560
10561 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10562 {
10563         int i;
10564         float f;
10565         const float *v;
10566         const float *n;
10567         float *c;
10568         //vec3_t eyedir;
10569
10570         // fake shading
10571         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10572         rsurface.passcolor4f_vertexbuffer = 0;
10573         rsurface.passcolor4f_bufferoffset = 0;
10574         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)
10575         {
10576                 f = -DotProduct(r_refdef.view.forward, n);
10577                 f = max(0, f);
10578                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10579                 f *= r_refdef.lightmapintensity;
10580                 Vector4Set(c, f, f, f, 1);
10581         }
10582 }
10583
10584 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10585 {
10586         RSurf_DrawBatch_GL11_ApplyFakeLight();
10587         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10588         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10589         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10590         GL_Color(r, g, b, a);
10591         RSurf_DrawBatch();
10592 }
10593
10594 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10595 {
10596         int i;
10597         float f;
10598         float alpha;
10599         const float *v;
10600         const float *n;
10601         float *c;
10602         vec3_t ambientcolor;
10603         vec3_t diffusecolor;
10604         vec3_t lightdir;
10605         // TODO: optimize
10606         // model lighting
10607         VectorCopy(rsurface.modellight_lightdir, lightdir);
10608         f = 0.5f * r_refdef.lightmapintensity;
10609         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10610         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10611         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10612         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10613         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10614         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10615         alpha = *a;
10616         if (VectorLength2(diffusecolor) > 0)
10617         {
10618                 // q3-style directional shading
10619                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10620                 rsurface.passcolor4f_vertexbuffer = 0;
10621                 rsurface.passcolor4f_bufferoffset = 0;
10622                 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)
10623                 {
10624                         if ((f = DotProduct(n, lightdir)) > 0)
10625                                 VectorMA(ambientcolor, f, diffusecolor, c);
10626                         else
10627                                 VectorCopy(ambientcolor, c);
10628                         c[3] = alpha;
10629                 }
10630                 *r = 1;
10631                 *g = 1;
10632                 *b = 1;
10633                 *a = 1;
10634                 *applycolor = false;
10635         }
10636         else
10637         {
10638                 *r = ambientcolor[0];
10639                 *g = ambientcolor[1];
10640                 *b = ambientcolor[2];
10641                 rsurface.passcolor4f = NULL;
10642                 rsurface.passcolor4f_vertexbuffer = 0;
10643                 rsurface.passcolor4f_bufferoffset = 0;
10644         }
10645 }
10646
10647 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10648 {
10649         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10650         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10651         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10652         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10653         GL_Color(r, g, b, a);
10654         RSurf_DrawBatch();
10655 }
10656
10657 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10658 {
10659         int i;
10660         float f;
10661         const float *v;
10662         float *c;
10663
10664         // fake shading
10665         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10666         rsurface.passcolor4f_vertexbuffer = 0;
10667         rsurface.passcolor4f_bufferoffset = 0;
10668
10669         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10670         {
10671                 f = 1 - RSurf_FogVertex(v);
10672                 c[0] = r;
10673                 c[1] = g;
10674                 c[2] = b;
10675                 c[3] = f * a;
10676         }
10677 }
10678
10679 void RSurf_SetupDepthAndCulling(void)
10680 {
10681         // submodels are biased to avoid z-fighting with world surfaces that they
10682         // may be exactly overlapping (avoids z-fighting artifacts on certain
10683         // doors and things in Quake maps)
10684         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10685         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10686         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10687         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10688 }
10689
10690 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10691 {
10692         // transparent sky would be ridiculous
10693         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10694                 return;
10695         R_SetupShader_Generic_NoTexture(false, false);
10696         skyrenderlater = true;
10697         RSurf_SetupDepthAndCulling();
10698         GL_DepthMask(true);
10699         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10700         // skymasking on them, and Quake3 never did sky masking (unlike
10701         // software Quake and software Quake2), so disable the sky masking
10702         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10703         // and skymasking also looks very bad when noclipping outside the
10704         // level, so don't use it then either.
10705         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10706         {
10707                 R_Mesh_ResetTextureState();
10708                 if (skyrendermasked)
10709                 {
10710                         R_SetupShader_DepthOrShadow(false, false, false);
10711                         // depth-only (masking)
10712                         GL_ColorMask(0,0,0,0);
10713                         // just to make sure that braindead drivers don't draw
10714                         // anything despite that colormask...
10715                         GL_BlendFunc(GL_ZERO, GL_ONE);
10716                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10717                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10718                 }
10719                 else
10720                 {
10721                         R_SetupShader_Generic_NoTexture(false, false);
10722                         // fog sky
10723                         GL_BlendFunc(GL_ONE, GL_ZERO);
10724                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10725                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10726                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10727                 }
10728                 RSurf_DrawBatch();
10729                 if (skyrendermasked)
10730                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10731         }
10732         R_Mesh_ResetTextureState();
10733         GL_Color(1, 1, 1, 1);
10734 }
10735
10736 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10737 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10738 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10739 {
10740         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10741                 return;
10742         if (prepass)
10743         {
10744                 // render screenspace normalmap to texture
10745                 GL_DepthMask(true);
10746                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10747                 RSurf_DrawBatch();
10748                 return;
10749         }
10750
10751         // bind lightmap texture
10752
10753         // water/refraction/reflection/camera surfaces have to be handled specially
10754         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10755         {
10756                 int start, end, startplaneindex;
10757                 for (start = 0;start < texturenumsurfaces;start = end)
10758                 {
10759                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10760                         if(startplaneindex < 0)
10761                         {
10762                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10763                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10764                                 end = start + 1;
10765                                 continue;
10766                         }
10767                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10768                                 ;
10769                         // now that we have a batch using the same planeindex, render it
10770                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10771                         {
10772                                 // render water or distortion background
10773                                 GL_DepthMask(true);
10774                                 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);
10775                                 RSurf_DrawBatch();
10776                                 // blend surface on top
10777                                 GL_DepthMask(false);
10778                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10779                                 RSurf_DrawBatch();
10780                         }
10781                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10782                         {
10783                                 // render surface with reflection texture as input
10784                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10785                                 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);
10786                                 RSurf_DrawBatch();
10787                         }
10788                 }
10789                 return;
10790         }
10791
10792         // render surface batch normally
10793         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10794         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);
10795         RSurf_DrawBatch();
10796 }
10797
10798 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10799 {
10800         // OpenGL 1.3 path - anything not completely ancient
10801         qboolean applycolor;
10802         qboolean applyfog;
10803         int layerindex;
10804         const texturelayer_t *layer;
10805         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);
10806         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10807
10808         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10809         {
10810                 vec4_t layercolor;
10811                 int layertexrgbscale;
10812                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10813                 {
10814                         if (layerindex == 0)
10815                                 GL_AlphaTest(true);
10816                         else
10817                         {
10818                                 GL_AlphaTest(false);
10819                                 GL_DepthFunc(GL_EQUAL);
10820                         }
10821                 }
10822                 GL_DepthMask(layer->depthmask && writedepth);
10823                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10824                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10825                 {
10826                         layertexrgbscale = 4;
10827                         VectorScale(layer->color, 0.25f, layercolor);
10828                 }
10829                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10830                 {
10831                         layertexrgbscale = 2;
10832                         VectorScale(layer->color, 0.5f, layercolor);
10833                 }
10834                 else
10835                 {
10836                         layertexrgbscale = 1;
10837                         VectorScale(layer->color, 1.0f, layercolor);
10838                 }
10839                 layercolor[3] = layer->color[3];
10840                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10841                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10842                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10843                 switch (layer->type)
10844                 {
10845                 case TEXTURELAYERTYPE_LITTEXTURE:
10846                         // single-pass lightmapped texture with 2x rgbscale
10847                         R_Mesh_TexBind(0, r_texture_white);
10848                         R_Mesh_TexMatrix(0, NULL);
10849                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10850                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10851                         R_Mesh_TexBind(1, layer->texture);
10852                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10853                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10854                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10855                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10856                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10857                         else if (FAKELIGHT_ENABLED)
10858                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10859                         else if (rsurface.uselightmaptexture)
10860                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10861                         else
10862                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10863                         break;
10864                 case TEXTURELAYERTYPE_TEXTURE:
10865                         // singletexture unlit texture with transparency support
10866                         R_Mesh_TexBind(0, layer->texture);
10867                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10868                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10869                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10870                         R_Mesh_TexBind(1, 0);
10871                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10872                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10873                         break;
10874                 case TEXTURELAYERTYPE_FOG:
10875                         // singletexture fogging
10876                         if (layer->texture)
10877                         {
10878                                 R_Mesh_TexBind(0, layer->texture);
10879                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10880                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10881                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10882                         }
10883                         else
10884                         {
10885                                 R_Mesh_TexBind(0, 0);
10886                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10887                         }
10888                         R_Mesh_TexBind(1, 0);
10889                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10890                         // generate a color array for the fog pass
10891                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10892                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10893                         RSurf_DrawBatch();
10894                         break;
10895                 default:
10896                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10897                 }
10898         }
10899         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10900         {
10901                 GL_DepthFunc(GL_LEQUAL);
10902                 GL_AlphaTest(false);
10903         }
10904 }
10905
10906 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10907 {
10908         // OpenGL 1.1 - crusty old voodoo path
10909         qboolean applyfog;
10910         int layerindex;
10911         const texturelayer_t *layer;
10912         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);
10913         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10914
10915         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10916         {
10917                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10918                 {
10919                         if (layerindex == 0)
10920                                 GL_AlphaTest(true);
10921                         else
10922                         {
10923                                 GL_AlphaTest(false);
10924                                 GL_DepthFunc(GL_EQUAL);
10925                         }
10926                 }
10927                 GL_DepthMask(layer->depthmask && writedepth);
10928                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10929                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10930                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10931                 switch (layer->type)
10932                 {
10933                 case TEXTURELAYERTYPE_LITTEXTURE:
10934                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10935                         {
10936                                 // two-pass lit texture with 2x rgbscale
10937                                 // first the lightmap pass
10938                                 R_Mesh_TexBind(0, r_texture_white);
10939                                 R_Mesh_TexMatrix(0, NULL);
10940                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10941                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10942                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10943                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10944                                 else if (FAKELIGHT_ENABLED)
10945                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10946                                 else if (rsurface.uselightmaptexture)
10947                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10948                                 else
10949                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10950                                 // then apply the texture to it
10951                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10952                                 R_Mesh_TexBind(0, layer->texture);
10953                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10954                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10955                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10956                                 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);
10957                         }
10958                         else
10959                         {
10960                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10961                                 R_Mesh_TexBind(0, layer->texture);
10962                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10963                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10964                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10965                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10966                                         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);
10967                                 else if (FAKELIGHT_ENABLED)
10968                                         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);
10969                                 else
10970                                         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);
10971                         }
10972                         break;
10973                 case TEXTURELAYERTYPE_TEXTURE:
10974                         // singletexture unlit texture with transparency support
10975                         R_Mesh_TexBind(0, layer->texture);
10976                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10977                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10978                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10979                         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);
10980                         break;
10981                 case TEXTURELAYERTYPE_FOG:
10982                         // singletexture fogging
10983                         if (layer->texture)
10984                         {
10985                                 R_Mesh_TexBind(0, layer->texture);
10986                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10987                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10988                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10989                         }
10990                         else
10991                         {
10992                                 R_Mesh_TexBind(0, 0);
10993                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10994                         }
10995                         // generate a color array for the fog pass
10996                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10997                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10998                         RSurf_DrawBatch();
10999                         break;
11000                 default:
11001                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11002                 }
11003         }
11004         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11005         {
11006                 GL_DepthFunc(GL_LEQUAL);
11007                 GL_AlphaTest(false);
11008         }
11009 }
11010
11011 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11012 {
11013         int vi;
11014         int j;
11015         r_vertexgeneric_t *batchvertex;
11016         float c[4];
11017
11018 //      R_Mesh_ResetTextureState();
11019         R_SetupShader_Generic_NoTexture(false, false);
11020
11021         if(rsurface.texture && rsurface.texture->currentskinframe)
11022         {
11023                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11024                 c[3] *= rsurface.texture->currentalpha;
11025         }
11026         else
11027         {
11028                 c[0] = 1;
11029                 c[1] = 0;
11030                 c[2] = 1;
11031                 c[3] = 1;
11032         }
11033
11034         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11035         {
11036                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11037                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11038                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11039         }
11040
11041         // brighten it up (as texture value 127 means "unlit")
11042         c[0] *= 2 * r_refdef.view.colorscale;
11043         c[1] *= 2 * r_refdef.view.colorscale;
11044         c[2] *= 2 * r_refdef.view.colorscale;
11045
11046         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11047                 c[3] *= r_wateralpha.value;
11048
11049         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11050         {
11051                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11052                 GL_DepthMask(false);
11053         }
11054         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11055         {
11056                 GL_BlendFunc(GL_ONE, GL_ONE);
11057                 GL_DepthMask(false);
11058         }
11059         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11060         {
11061                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11062                 GL_DepthMask(false);
11063         }
11064         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11065         {
11066                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11067                 GL_DepthMask(false);
11068         }
11069         else
11070         {
11071                 GL_BlendFunc(GL_ONE, GL_ZERO);
11072                 GL_DepthMask(writedepth);
11073         }
11074
11075         if (r_showsurfaces.integer == 3)
11076         {
11077                 rsurface.passcolor4f = NULL;
11078
11079                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11080                 {
11081                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11082
11083                         rsurface.passcolor4f = NULL;
11084                         rsurface.passcolor4f_vertexbuffer = 0;
11085                         rsurface.passcolor4f_bufferoffset = 0;
11086                 }
11087                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11088                 {
11089                         qboolean applycolor = true;
11090                         float one = 1.0;
11091
11092                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11093
11094                         r_refdef.lightmapintensity = 1;
11095                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11096                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11097                 }
11098                 else if (FAKELIGHT_ENABLED)
11099                 {
11100                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11101
11102                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11103                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11104                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11105                 }
11106                 else
11107                 {
11108                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11109
11110                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11111                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11112                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11113                 }
11114
11115                 if(!rsurface.passcolor4f)
11116                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11117
11118                 RSurf_DrawBatch_GL11_ApplyAmbient();
11119                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11120                 if(r_refdef.fogenabled)
11121                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11122                 RSurf_DrawBatch_GL11_ClampColor();
11123
11124                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11125                 R_SetupShader_Generic_NoTexture(false, false);
11126                 RSurf_DrawBatch();
11127         }
11128         else if (!r_refdef.view.showdebug)
11129         {
11130                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11131                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11132                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11133                 {
11134                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11135                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11136                 }
11137                 R_Mesh_PrepareVertices_Generic_Unlock();
11138                 RSurf_DrawBatch();
11139         }
11140         else if (r_showsurfaces.integer == 4)
11141         {
11142                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11143                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11144                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11145                 {
11146                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11147                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11148                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11149                 }
11150                 R_Mesh_PrepareVertices_Generic_Unlock();
11151                 RSurf_DrawBatch();
11152         }
11153         else if (r_showsurfaces.integer == 2)
11154         {
11155                 const int *e;
11156                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11157                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11158                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11159                 {
11160                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11161                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11162                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11163                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11164                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11165                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11166                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11167                 }
11168                 R_Mesh_PrepareVertices_Generic_Unlock();
11169                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11170         }
11171         else
11172         {
11173                 int texturesurfaceindex;
11174                 int k;
11175                 const msurface_t *surface;
11176                 float surfacecolor4f[4];
11177                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11178                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11179                 vi = 0;
11180                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11181                 {
11182                         surface = texturesurfacelist[texturesurfaceindex];
11183                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11184                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11185                         for (j = 0;j < surface->num_vertices;j++)
11186                         {
11187                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11188                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11189                                 vi++;
11190                         }
11191                 }
11192                 R_Mesh_PrepareVertices_Generic_Unlock();
11193                 RSurf_DrawBatch();
11194         }
11195 }
11196
11197 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11198 {
11199         CHECKGLERROR
11200         RSurf_SetupDepthAndCulling();
11201         if (r_showsurfaces.integer)
11202         {
11203                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11204                 return;
11205         }
11206         switch (vid.renderpath)
11207         {
11208         case RENDERPATH_GL20:
11209         case RENDERPATH_D3D9:
11210         case RENDERPATH_D3D10:
11211         case RENDERPATH_D3D11:
11212         case RENDERPATH_SOFT:
11213         case RENDERPATH_GLES2:
11214                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11215                 break;
11216         case RENDERPATH_GL13:
11217         case RENDERPATH_GLES1:
11218                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11219                 break;
11220         case RENDERPATH_GL11:
11221                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11222                 break;
11223         }
11224         CHECKGLERROR
11225 }
11226
11227 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11228 {
11229         CHECKGLERROR
11230         RSurf_SetupDepthAndCulling();
11231         if (r_showsurfaces.integer)
11232         {
11233                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11234                 return;
11235         }
11236         switch (vid.renderpath)
11237         {
11238         case RENDERPATH_GL20:
11239         case RENDERPATH_D3D9:
11240         case RENDERPATH_D3D10:
11241         case RENDERPATH_D3D11:
11242         case RENDERPATH_SOFT:
11243         case RENDERPATH_GLES2:
11244                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11245                 break;
11246         case RENDERPATH_GL13:
11247         case RENDERPATH_GLES1:
11248                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11249                 break;
11250         case RENDERPATH_GL11:
11251                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11252                 break;
11253         }
11254         CHECKGLERROR
11255 }
11256
11257 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11258 {
11259         int i, j;
11260         int texturenumsurfaces, endsurface;
11261         texture_t *texture;
11262         const msurface_t *surface;
11263         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11264
11265         // if the model is static it doesn't matter what value we give for
11266         // wantnormals and wanttangents, so this logic uses only rules applicable
11267         // to a model, knowing that they are meaningless otherwise
11268         if (ent == r_refdef.scene.worldentity)
11269                 RSurf_ActiveWorldEntity();
11270         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11271                 RSurf_ActiveModelEntity(ent, false, false, false);
11272         else
11273         {
11274                 switch (vid.renderpath)
11275                 {
11276                 case RENDERPATH_GL20:
11277                 case RENDERPATH_D3D9:
11278                 case RENDERPATH_D3D10:
11279                 case RENDERPATH_D3D11:
11280                 case RENDERPATH_SOFT:
11281                 case RENDERPATH_GLES2:
11282                         RSurf_ActiveModelEntity(ent, true, true, false);
11283                         break;
11284                 case RENDERPATH_GL11:
11285                 case RENDERPATH_GL13:
11286                 case RENDERPATH_GLES1:
11287                         RSurf_ActiveModelEntity(ent, true, false, false);
11288                         break;
11289                 }
11290         }
11291
11292         if (r_transparentdepthmasking.integer)
11293         {
11294                 qboolean setup = false;
11295                 for (i = 0;i < numsurfaces;i = j)
11296                 {
11297                         j = i + 1;
11298                         surface = rsurface.modelsurfaces + surfacelist[i];
11299                         texture = surface->texture;
11300                         rsurface.texture = R_GetCurrentTexture(texture);
11301                         rsurface.lightmaptexture = NULL;
11302                         rsurface.deluxemaptexture = NULL;
11303                         rsurface.uselightmaptexture = false;
11304                         // scan ahead until we find a different texture
11305                         endsurface = min(i + 1024, numsurfaces);
11306                         texturenumsurfaces = 0;
11307                         texturesurfacelist[texturenumsurfaces++] = surface;
11308                         for (;j < endsurface;j++)
11309                         {
11310                                 surface = rsurface.modelsurfaces + surfacelist[j];
11311                                 if (texture != surface->texture)
11312                                         break;
11313                                 texturesurfacelist[texturenumsurfaces++] = surface;
11314                         }
11315                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11316                                 continue;
11317                         // render the range of surfaces as depth
11318                         if (!setup)
11319                         {
11320                                 setup = true;
11321                                 GL_ColorMask(0,0,0,0);
11322                                 GL_Color(1,1,1,1);
11323                                 GL_DepthTest(true);
11324                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11325                                 GL_DepthMask(true);
11326 //                              R_Mesh_ResetTextureState();
11327                         }
11328                         RSurf_SetupDepthAndCulling();
11329                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11330                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11331                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11332                         RSurf_DrawBatch();
11333                 }
11334                 if (setup)
11335                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11336         }
11337
11338         for (i = 0;i < numsurfaces;i = j)
11339         {
11340                 j = i + 1;
11341                 surface = rsurface.modelsurfaces + surfacelist[i];
11342                 texture = surface->texture;
11343                 rsurface.texture = R_GetCurrentTexture(texture);
11344                 // scan ahead until we find a different texture
11345                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11346                 texturenumsurfaces = 0;
11347                 texturesurfacelist[texturenumsurfaces++] = surface;
11348                 if(FAKELIGHT_ENABLED)
11349                 {
11350                         rsurface.lightmaptexture = NULL;
11351                         rsurface.deluxemaptexture = NULL;
11352                         rsurface.uselightmaptexture = false;
11353                         for (;j < endsurface;j++)
11354                         {
11355                                 surface = rsurface.modelsurfaces + surfacelist[j];
11356                                 if (texture != surface->texture)
11357                                         break;
11358                                 texturesurfacelist[texturenumsurfaces++] = surface;
11359                         }
11360                 }
11361                 else
11362                 {
11363                         rsurface.lightmaptexture = surface->lightmaptexture;
11364                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11365                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11366                         for (;j < endsurface;j++)
11367                         {
11368                                 surface = rsurface.modelsurfaces + surfacelist[j];
11369                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11370                                         break;
11371                                 texturesurfacelist[texturenumsurfaces++] = surface;
11372                         }
11373                 }
11374                 // render the range of surfaces
11375                 if (ent == r_refdef.scene.worldentity)
11376                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11377                 else
11378                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11379         }
11380         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11381 }
11382
11383 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11384 {
11385         // transparent surfaces get pushed off into the transparent queue
11386         int surfacelistindex;
11387         const msurface_t *surface;
11388         vec3_t tempcenter, center;
11389         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11390         {
11391                 surface = texturesurfacelist[surfacelistindex];
11392                 if (r_transparent_sortsurfacesbynearest.integer)
11393                 {
11394                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11395                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11396                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11397                 }
11398                 else
11399                 {
11400                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11401                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11402                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11403                 }
11404                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11405                 if (rsurface.entity->transparent_offset) // transparent offset
11406                 {
11407                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11408                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11409                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11410                 }
11411                 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);
11412         }
11413 }
11414
11415 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11416 {
11417         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11418                 return;
11419         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11420                 return;
11421         RSurf_SetupDepthAndCulling();
11422         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11423         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11424         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11425         RSurf_DrawBatch();
11426 }
11427
11428 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11429 {
11430         CHECKGLERROR
11431         if (depthonly)
11432                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11433         else if (prepass)
11434         {
11435                 if (!rsurface.texture->currentnumlayers)
11436                         return;
11437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11438                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11439                 else
11440                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11441         }
11442         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11443                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11444         else if (!rsurface.texture->currentnumlayers)
11445                 return;
11446         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11447         {
11448                 // in the deferred case, transparent surfaces were queued during prepass
11449                 if (!r_shadow_usingdeferredprepass)
11450                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11451         }
11452         else
11453         {
11454                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11455                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11456         }
11457         CHECKGLERROR
11458 }
11459
11460 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11461 {
11462         int i, j;
11463         texture_t *texture;
11464         R_FrameData_SetMark();
11465         // break the surface list down into batches by texture and use of lightmapping
11466         for (i = 0;i < numsurfaces;i = j)
11467         {
11468                 j = i + 1;
11469                 // texture is the base texture pointer, rsurface.texture is the
11470                 // current frame/skin the texture is directing us to use (for example
11471                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11472                 // use skin 1 instead)
11473                 texture = surfacelist[i]->texture;
11474                 rsurface.texture = R_GetCurrentTexture(texture);
11475                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11476                 {
11477                         // if this texture is not the kind we want, skip ahead to the next one
11478                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11479                                 ;
11480                         continue;
11481                 }
11482                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11483                 {
11484                         rsurface.lightmaptexture = NULL;
11485                         rsurface.deluxemaptexture = NULL;
11486                         rsurface.uselightmaptexture = false;
11487                         // simply scan ahead until we find a different texture or lightmap state
11488                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11489                                 ;
11490                 }
11491                 else
11492                 {
11493                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11494                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11495                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11496                         // simply scan ahead until we find a different texture or lightmap state
11497                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11498                                 ;
11499                 }
11500                 // render the range of surfaces
11501                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11502         }
11503         R_FrameData_ReturnToMark();
11504 }
11505
11506 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11507 {
11508         CHECKGLERROR
11509         if (depthonly)
11510                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11511         else if (prepass)
11512         {
11513                 if (!rsurface.texture->currentnumlayers)
11514                         return;
11515                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11516                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11517                 else
11518                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11519         }
11520         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11521                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11522         else if (!rsurface.texture->currentnumlayers)
11523                 return;
11524         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11525         {
11526                 // in the deferred case, transparent surfaces were queued during prepass
11527                 if (!r_shadow_usingdeferredprepass)
11528                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11529         }
11530         else
11531         {
11532                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11533                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11534         }
11535         CHECKGLERROR
11536 }
11537
11538 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11539 {
11540         int i, j;
11541         texture_t *texture;
11542         R_FrameData_SetMark();
11543         // break the surface list down into batches by texture and use of lightmapping
11544         for (i = 0;i < numsurfaces;i = j)
11545         {
11546                 j = i + 1;
11547                 // texture is the base texture pointer, rsurface.texture is the
11548                 // current frame/skin the texture is directing us to use (for example
11549                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11550                 // use skin 1 instead)
11551                 texture = surfacelist[i]->texture;
11552                 rsurface.texture = R_GetCurrentTexture(texture);
11553                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11554                 {
11555                         // if this texture is not the kind we want, skip ahead to the next one
11556                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11557                                 ;
11558                         continue;
11559                 }
11560                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11561                 {
11562                         rsurface.lightmaptexture = NULL;
11563                         rsurface.deluxemaptexture = NULL;
11564                         rsurface.uselightmaptexture = false;
11565                         // simply scan ahead until we find a different texture or lightmap state
11566                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11567                                 ;
11568                 }
11569                 else
11570                 {
11571                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11572                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11573                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11574                         // simply scan ahead until we find a different texture or lightmap state
11575                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11576                                 ;
11577                 }
11578                 // render the range of surfaces
11579                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11580         }
11581         R_FrameData_ReturnToMark();
11582 }
11583
11584 float locboxvertex3f[6*4*3] =
11585 {
11586         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11587         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11588         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11589         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11590         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11591         1,0,0, 0,0,0, 0,1,0, 1,1,0
11592 };
11593
11594 unsigned short locboxelements[6*2*3] =
11595 {
11596          0, 1, 2, 0, 2, 3,
11597          4, 5, 6, 4, 6, 7,
11598          8, 9,10, 8,10,11,
11599         12,13,14, 12,14,15,
11600         16,17,18, 16,18,19,
11601         20,21,22, 20,22,23
11602 };
11603
11604 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11605 {
11606         int i, j;
11607         cl_locnode_t *loc = (cl_locnode_t *)ent;
11608         vec3_t mins, size;
11609         float vertex3f[6*4*3];
11610         CHECKGLERROR
11611         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11612         GL_DepthMask(false);
11613         GL_DepthRange(0, 1);
11614         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11615         GL_DepthTest(true);
11616         GL_CullFace(GL_NONE);
11617         R_EntityMatrix(&identitymatrix);
11618
11619 //      R_Mesh_ResetTextureState();
11620
11621         i = surfacelist[0];
11622         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11623                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11624                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11625                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11626
11627         if (VectorCompare(loc->mins, loc->maxs))
11628         {
11629                 VectorSet(size, 2, 2, 2);
11630                 VectorMA(loc->mins, -0.5f, size, mins);
11631         }
11632         else
11633         {
11634                 VectorCopy(loc->mins, mins);
11635                 VectorSubtract(loc->maxs, loc->mins, size);
11636         }
11637
11638         for (i = 0;i < 6*4*3;)
11639                 for (j = 0;j < 3;j++, i++)
11640                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11641
11642         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11643         R_SetupShader_Generic_NoTexture(false, false);
11644         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11645 }
11646
11647 void R_DrawLocs(void)
11648 {
11649         int index;
11650         cl_locnode_t *loc, *nearestloc;
11651         vec3_t center;
11652         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11653         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11654         {
11655                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11656                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11657         }
11658 }
11659
11660 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11661 {
11662         if (decalsystem->decals)
11663                 Mem_Free(decalsystem->decals);
11664         memset(decalsystem, 0, sizeof(*decalsystem));
11665 }
11666
11667 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, unsigned int decalsequence)
11668 {
11669         tridecal_t *decal;
11670         tridecal_t *decals;
11671         int i;
11672
11673         // expand or initialize the system
11674         if (decalsystem->maxdecals <= decalsystem->numdecals)
11675         {
11676                 decalsystem_t old = *decalsystem;
11677                 qboolean useshortelements;
11678                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11679                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11680                 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)));
11681                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11682                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11683                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11684                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11685                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11686                 if (decalsystem->numdecals)
11687                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11688                 if (old.decals)
11689                         Mem_Free(old.decals);
11690                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11691                         decalsystem->element3i[i] = i;
11692                 if (useshortelements)
11693                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11694                                 decalsystem->element3s[i] = i;
11695         }
11696
11697         // grab a decal and search for another free slot for the next one
11698         decals = decalsystem->decals;
11699         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11700         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11701                 ;
11702         decalsystem->freedecal = i;
11703         if (decalsystem->numdecals <= i)
11704                 decalsystem->numdecals = i + 1;
11705
11706         // initialize the decal
11707         decal->lived = 0;
11708         decal->triangleindex = triangleindex;
11709         decal->surfaceindex = surfaceindex;
11710         decal->decalsequence = decalsequence;
11711         decal->color4f[0][0] = c0[0];
11712         decal->color4f[0][1] = c0[1];
11713         decal->color4f[0][2] = c0[2];
11714         decal->color4f[0][3] = 1;
11715         decal->color4f[1][0] = c1[0];
11716         decal->color4f[1][1] = c1[1];
11717         decal->color4f[1][2] = c1[2];
11718         decal->color4f[1][3] = 1;
11719         decal->color4f[2][0] = c2[0];
11720         decal->color4f[2][1] = c2[1];
11721         decal->color4f[2][2] = c2[2];
11722         decal->color4f[2][3] = 1;
11723         decal->vertex3f[0][0] = v0[0];
11724         decal->vertex3f[0][1] = v0[1];
11725         decal->vertex3f[0][2] = v0[2];
11726         decal->vertex3f[1][0] = v1[0];
11727         decal->vertex3f[1][1] = v1[1];
11728         decal->vertex3f[1][2] = v1[2];
11729         decal->vertex3f[2][0] = v2[0];
11730         decal->vertex3f[2][1] = v2[1];
11731         decal->vertex3f[2][2] = v2[2];
11732         decal->texcoord2f[0][0] = t0[0];
11733         decal->texcoord2f[0][1] = t0[1];
11734         decal->texcoord2f[1][0] = t1[0];
11735         decal->texcoord2f[1][1] = t1[1];
11736         decal->texcoord2f[2][0] = t2[0];
11737         decal->texcoord2f[2][1] = t2[1];
11738         TriangleNormal(v0, v1, v2, decal->plane);
11739         VectorNormalize(decal->plane);
11740         decal->plane[3] = DotProduct(v0, decal->plane);
11741 }
11742
11743 extern cvar_t cl_decals_bias;
11744 extern cvar_t cl_decals_models;
11745 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11746 // baseparms, parms, temps
11747 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11748 {
11749         int cornerindex;
11750         int index;
11751         float v[9][3];
11752         const float *vertex3f;
11753         const float *normal3f;
11754         int numpoints;
11755         float points[2][9][3];
11756         float temp[3];
11757         float tc[9][2];
11758         float f;
11759         float c[9][4];
11760         const int *e;
11761
11762         e = rsurface.modelelement3i + 3*triangleindex;
11763
11764         vertex3f = rsurface.modelvertex3f;
11765         normal3f = rsurface.modelnormal3f;
11766
11767         if (normal3f)
11768         {
11769                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11770                 {
11771                         index = 3*e[cornerindex];
11772                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11773                 }
11774         }
11775         else
11776         {
11777                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11778                 {
11779                         index = 3*e[cornerindex];
11780                         VectorCopy(vertex3f + index, v[cornerindex]);
11781                 }
11782         }
11783
11784         // cull backfaces
11785         //TriangleNormal(v[0], v[1], v[2], normal);
11786         //if (DotProduct(normal, localnormal) < 0.0f)
11787         //      continue;
11788         // clip by each of the box planes formed from the projection matrix
11789         // if anything survives, we emit the decal
11790         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]);
11791         if (numpoints < 3)
11792                 return;
11793         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]);
11794         if (numpoints < 3)
11795                 return;
11796         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]);
11797         if (numpoints < 3)
11798                 return;
11799         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]);
11800         if (numpoints < 3)
11801                 return;
11802         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]);
11803         if (numpoints < 3)
11804                 return;
11805         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]);
11806         if (numpoints < 3)
11807                 return;
11808         // some part of the triangle survived, so we have to accept it...
11809         if (dynamic)
11810         {
11811                 // dynamic always uses the original triangle
11812                 numpoints = 3;
11813                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11814                 {
11815                         index = 3*e[cornerindex];
11816                         VectorCopy(vertex3f + index, v[cornerindex]);
11817                 }
11818         }
11819         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11820         {
11821                 // convert vertex positions to texcoords
11822                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11823                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11824                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11825                 // calculate distance fade from the projection origin
11826                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11827                 f = bound(0.0f, f, 1.0f);
11828                 c[cornerindex][0] = r * f;
11829                 c[cornerindex][1] = g * f;
11830                 c[cornerindex][2] = b * f;
11831                 c[cornerindex][3] = 1.0f;
11832                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11833         }
11834         if (dynamic)
11835                 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);
11836         else
11837                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11838                         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);
11839 }
11840 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, unsigned int decalsequence)
11841 {
11842         matrix4x4_t projection;
11843         decalsystem_t *decalsystem;
11844         qboolean dynamic;
11845         dp_model_t *model;
11846         const msurface_t *surface;
11847         const msurface_t *surfaces;
11848         const int *surfacelist;
11849         const texture_t *texture;
11850         int numtriangles;
11851         int numsurfacelist;
11852         int surfacelistindex;
11853         int surfaceindex;
11854         int triangleindex;
11855         float localorigin[3];
11856         float localnormal[3];
11857         float localmins[3];
11858         float localmaxs[3];
11859         float localsize;
11860         //float normal[3];
11861         float planes[6][4];
11862         float angles[3];
11863         bih_t *bih;
11864         int bih_triangles_count;
11865         int bih_triangles[256];
11866         int bih_surfaces[256];
11867
11868         decalsystem = &ent->decalsystem;
11869         model = ent->model;
11870         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11871         {
11872                 R_DecalSystem_Reset(&ent->decalsystem);
11873                 return;
11874         }
11875
11876         if (!model->brush.data_leafs && !cl_decals_models.integer)
11877         {
11878                 if (decalsystem->model)
11879                         R_DecalSystem_Reset(decalsystem);
11880                 return;
11881         }
11882
11883         if (decalsystem->model != model)
11884                 R_DecalSystem_Reset(decalsystem);
11885         decalsystem->model = model;
11886
11887         RSurf_ActiveModelEntity(ent, true, false, false);
11888
11889         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11890         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11891         VectorNormalize(localnormal);
11892         localsize = worldsize*rsurface.inversematrixscale;
11893         localmins[0] = localorigin[0] - localsize;
11894         localmins[1] = localorigin[1] - localsize;
11895         localmins[2] = localorigin[2] - localsize;
11896         localmaxs[0] = localorigin[0] + localsize;
11897         localmaxs[1] = localorigin[1] + localsize;
11898         localmaxs[2] = localorigin[2] + localsize;
11899
11900         //VectorCopy(localnormal, planes[4]);
11901         //VectorVectors(planes[4], planes[2], planes[0]);
11902         AnglesFromVectors(angles, localnormal, NULL, false);
11903         AngleVectors(angles, planes[0], planes[2], planes[4]);
11904         VectorNegate(planes[0], planes[1]);
11905         VectorNegate(planes[2], planes[3]);
11906         VectorNegate(planes[4], planes[5]);
11907         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11908         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11909         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11910         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11911         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11912         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11913
11914 #if 1
11915 // works
11916 {
11917         matrix4x4_t forwardprojection;
11918         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11919         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11920 }
11921 #else
11922 // broken
11923 {
11924         float projectionvector[4][3];
11925         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11926         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11927         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11928         projectionvector[0][0] = planes[0][0] * ilocalsize;
11929         projectionvector[0][1] = planes[1][0] * ilocalsize;
11930         projectionvector[0][2] = planes[2][0] * ilocalsize;
11931         projectionvector[1][0] = planes[0][1] * ilocalsize;
11932         projectionvector[1][1] = planes[1][1] * ilocalsize;
11933         projectionvector[1][2] = planes[2][1] * ilocalsize;
11934         projectionvector[2][0] = planes[0][2] * ilocalsize;
11935         projectionvector[2][1] = planes[1][2] * ilocalsize;
11936         projectionvector[2][2] = planes[2][2] * ilocalsize;
11937         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11938         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11939         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11940         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11941 }
11942 #endif
11943
11944         dynamic = model->surfmesh.isanimated;
11945         numsurfacelist = model->nummodelsurfaces;
11946         surfacelist = model->sortedmodelsurfaces;
11947         surfaces = model->data_surfaces;
11948
11949         bih = NULL;
11950         bih_triangles_count = -1;
11951         if(!dynamic)
11952         {
11953                 if(model->render_bih.numleafs)
11954                         bih = &model->render_bih;
11955                 else if(model->collision_bih.numleafs)
11956                         bih = &model->collision_bih;
11957         }
11958         if(bih)
11959                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11960         if(bih_triangles_count == 0)
11961                 return;
11962         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11963                 return;
11964         if(bih_triangles_count > 0)
11965         {
11966                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11967                 {
11968                         surfaceindex = bih_surfaces[triangleindex];
11969                         surface = surfaces + surfaceindex;
11970                         texture = surface->texture;
11971                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11972                                 continue;
11973                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11974                                 continue;
11975                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11976                 }
11977         }
11978         else
11979         {
11980                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11981                 {
11982                         surfaceindex = surfacelist[surfacelistindex];
11983                         surface = surfaces + surfaceindex;
11984                         // check cull box first because it rejects more than any other check
11985                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11986                                 continue;
11987                         // skip transparent surfaces
11988                         texture = surface->texture;
11989                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11990                                 continue;
11991                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11992                                 continue;
11993                         numtriangles = surface->num_triangles;
11994                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11995                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11996                 }
11997         }
11998 }
11999
12000 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12001 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, unsigned int decalsequence)
12002 {
12003         int renderentityindex;
12004         float worldmins[3];
12005         float worldmaxs[3];
12006         entity_render_t *ent;
12007
12008         if (!cl_decals_newsystem.integer)
12009                 return;
12010
12011         worldmins[0] = worldorigin[0] - worldsize;
12012         worldmins[1] = worldorigin[1] - worldsize;
12013         worldmins[2] = worldorigin[2] - worldsize;
12014         worldmaxs[0] = worldorigin[0] + worldsize;
12015         worldmaxs[1] = worldorigin[1] + worldsize;
12016         worldmaxs[2] = worldorigin[2] + worldsize;
12017
12018         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12019
12020         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12021         {
12022                 ent = r_refdef.scene.entities[renderentityindex];
12023                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12024                         continue;
12025
12026                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12027         }
12028 }
12029
12030 typedef struct r_decalsystem_splatqueue_s
12031 {
12032         vec3_t worldorigin;
12033         vec3_t worldnormal;
12034         float color[4];
12035         float tcrange[4];
12036         float worldsize;
12037         unsigned int decalsequence;
12038 }
12039 r_decalsystem_splatqueue_t;
12040
12041 int r_decalsystem_numqueued = 0;
12042 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12043
12044 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)
12045 {
12046         r_decalsystem_splatqueue_t *queue;
12047
12048         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12049                 return;
12050
12051         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12052         VectorCopy(worldorigin, queue->worldorigin);
12053         VectorCopy(worldnormal, queue->worldnormal);
12054         Vector4Set(queue->color, r, g, b, a);
12055         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12056         queue->worldsize = worldsize;
12057         queue->decalsequence = cl.decalsequence++;
12058 }
12059
12060 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12061 {
12062         int i;
12063         r_decalsystem_splatqueue_t *queue;
12064
12065         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12066                 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);
12067         r_decalsystem_numqueued = 0;
12068 }
12069
12070 extern cvar_t cl_decals_max;
12071 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12072 {
12073         int i;
12074         decalsystem_t *decalsystem = &ent->decalsystem;
12075         int numdecals;
12076         unsigned int killsequence;
12077         tridecal_t *decal;
12078         float frametime;
12079         float lifetime;
12080
12081         if (!decalsystem->numdecals)
12082                 return;
12083
12084         if (r_showsurfaces.integer)
12085                 return;
12086
12087         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12088         {
12089                 R_DecalSystem_Reset(decalsystem);
12090                 return;
12091         }
12092
12093         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12094         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12095
12096         if (decalsystem->lastupdatetime)
12097                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12098         else
12099                 frametime = 0;
12100         decalsystem->lastupdatetime = r_refdef.scene.time;
12101         numdecals = decalsystem->numdecals;
12102
12103         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12104         {
12105                 if (decal->color4f[0][3])
12106                 {
12107                         decal->lived += frametime;
12108                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12109                         {
12110                                 memset(decal, 0, sizeof(*decal));
12111                                 if (decalsystem->freedecal > i)
12112                                         decalsystem->freedecal = i;
12113                         }
12114                 }
12115         }
12116         decal = decalsystem->decals;
12117         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12118                 numdecals--;
12119
12120         // collapse the array by shuffling the tail decals into the gaps
12121         for (;;)
12122         {
12123                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12124                         decalsystem->freedecal++;
12125                 if (decalsystem->freedecal == numdecals)
12126                         break;
12127                 decal[decalsystem->freedecal] = decal[--numdecals];
12128         }
12129
12130         decalsystem->numdecals = numdecals;
12131
12132         if (numdecals <= 0)
12133         {
12134                 // if there are no decals left, reset decalsystem
12135                 R_DecalSystem_Reset(decalsystem);
12136         }
12137 }
12138
12139 extern skinframe_t *decalskinframe;
12140 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12141 {
12142         int i;
12143         decalsystem_t *decalsystem = &ent->decalsystem;
12144         int numdecals;
12145         tridecal_t *decal;
12146         float faderate;
12147         float alpha;
12148         float *v3f;
12149         float *c4f;
12150         float *t2f;
12151         const int *e;
12152         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12153         int numtris = 0;
12154
12155         numdecals = decalsystem->numdecals;
12156         if (!numdecals)
12157                 return;
12158
12159         if (r_showsurfaces.integer)
12160                 return;
12161
12162         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12163         {
12164                 R_DecalSystem_Reset(decalsystem);
12165                 return;
12166         }
12167
12168         // if the model is static it doesn't matter what value we give for
12169         // wantnormals and wanttangents, so this logic uses only rules applicable
12170         // to a model, knowing that they are meaningless otherwise
12171         if (ent == r_refdef.scene.worldentity)
12172                 RSurf_ActiveWorldEntity();
12173         else
12174                 RSurf_ActiveModelEntity(ent, false, false, false);
12175
12176         decalsystem->lastupdatetime = r_refdef.scene.time;
12177
12178         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12179
12180         // update vertex positions for animated models
12181         v3f = decalsystem->vertex3f;
12182         c4f = decalsystem->color4f;
12183         t2f = decalsystem->texcoord2f;
12184         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12185         {
12186                 if (!decal->color4f[0][3])
12187                         continue;
12188
12189                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12190                         continue;
12191
12192                 // skip backfaces
12193                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12194                         continue;
12195
12196                 // update color values for fading decals
12197                 if (decal->lived >= cl_decals_time.value)
12198                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12199                 else
12200                         alpha = 1.0f;
12201
12202                 c4f[ 0] = decal->color4f[0][0] * alpha;
12203                 c4f[ 1] = decal->color4f[0][1] * alpha;
12204                 c4f[ 2] = decal->color4f[0][2] * alpha;
12205                 c4f[ 3] = 1;
12206                 c4f[ 4] = decal->color4f[1][0] * alpha;
12207                 c4f[ 5] = decal->color4f[1][1] * alpha;
12208                 c4f[ 6] = decal->color4f[1][2] * alpha;
12209                 c4f[ 7] = 1;
12210                 c4f[ 8] = decal->color4f[2][0] * alpha;
12211                 c4f[ 9] = decal->color4f[2][1] * alpha;
12212                 c4f[10] = decal->color4f[2][2] * alpha;
12213                 c4f[11] = 1;
12214
12215                 t2f[0] = decal->texcoord2f[0][0];
12216                 t2f[1] = decal->texcoord2f[0][1];
12217                 t2f[2] = decal->texcoord2f[1][0];
12218                 t2f[3] = decal->texcoord2f[1][1];
12219                 t2f[4] = decal->texcoord2f[2][0];
12220                 t2f[5] = decal->texcoord2f[2][1];
12221
12222                 // update vertex positions for animated models
12223                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12224                 {
12225                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12226                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12227                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12228                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12229                 }
12230                 else
12231                 {
12232                         VectorCopy(decal->vertex3f[0], v3f);
12233                         VectorCopy(decal->vertex3f[1], v3f + 3);
12234                         VectorCopy(decal->vertex3f[2], v3f + 6);
12235                 }
12236
12237                 if (r_refdef.fogenabled)
12238                 {
12239                         alpha = RSurf_FogVertex(v3f);
12240                         VectorScale(c4f, alpha, c4f);
12241                         alpha = RSurf_FogVertex(v3f + 3);
12242                         VectorScale(c4f + 4, alpha, c4f + 4);
12243                         alpha = RSurf_FogVertex(v3f + 6);
12244                         VectorScale(c4f + 8, alpha, c4f + 8);
12245                 }
12246
12247                 v3f += 9;
12248                 c4f += 12;
12249                 t2f += 6;
12250                 numtris++;
12251         }
12252
12253         if (numtris > 0)
12254         {
12255                 r_refdef.stats[r_stat_drawndecals] += numtris;
12256
12257                 // now render the decals all at once
12258                 // (this assumes they all use one particle font texture!)
12259                 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);
12260 //              R_Mesh_ResetTextureState();
12261                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12262                 GL_DepthMask(false);
12263                 GL_DepthRange(0, 1);
12264                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12265                 GL_DepthTest(true);
12266                 GL_CullFace(GL_NONE);
12267                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12268                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12269                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12270         }
12271 }
12272
12273 static void R_DrawModelDecals(void)
12274 {
12275         int i, numdecals;
12276
12277         // fade faster when there are too many decals
12278         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12279         for (i = 0;i < r_refdef.scene.numentities;i++)
12280                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12281
12282         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12283         for (i = 0;i < r_refdef.scene.numentities;i++)
12284                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12285                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12286
12287         R_DecalSystem_ApplySplatEntitiesQueue();
12288
12289         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12290         for (i = 0;i < r_refdef.scene.numentities;i++)
12291                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12292
12293         r_refdef.stats[r_stat_totaldecals] += numdecals;
12294
12295         if (r_showsurfaces.integer)
12296                 return;
12297
12298         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12299
12300         for (i = 0;i < r_refdef.scene.numentities;i++)
12301         {
12302                 if (!r_refdef.viewcache.entityvisible[i])
12303                         continue;
12304                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12305                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12306         }
12307 }
12308
12309 extern cvar_t mod_collision_bih;
12310 static void R_DrawDebugModel(void)
12311 {
12312         entity_render_t *ent = rsurface.entity;
12313         int i, j, flagsmask;
12314         const msurface_t *surface;
12315         dp_model_t *model = ent->model;
12316
12317         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12318                 return;
12319
12320         if (r_showoverdraw.value > 0)
12321         {
12322                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12323                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12324                 R_SetupShader_Generic_NoTexture(false, false);
12325                 GL_DepthTest(false);
12326                 GL_DepthMask(false);
12327                 GL_DepthRange(0, 1);
12328                 GL_BlendFunc(GL_ONE, GL_ONE);
12329                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12330                 {
12331                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12332                                 continue;
12333                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12334                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12335                         {
12336                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12337                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12338                                 if (!rsurface.texture->currentlayers->depthmask)
12339                                         GL_Color(c, 0, 0, 1.0f);
12340                                 else if (ent == r_refdef.scene.worldentity)
12341                                         GL_Color(c, c, c, 1.0f);
12342                                 else
12343                                         GL_Color(0, c, 0, 1.0f);
12344                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12345                                 RSurf_DrawBatch();
12346                         }
12347                 }
12348                 rsurface.texture = NULL;
12349         }
12350
12351         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12352
12353 //      R_Mesh_ResetTextureState();
12354         R_SetupShader_Generic_NoTexture(false, false);
12355         GL_DepthRange(0, 1);
12356         GL_DepthTest(!r_showdisabledepthtest.integer);
12357         GL_DepthMask(false);
12358         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12359
12360         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12361         {
12362                 int triangleindex;
12363                 int bihleafindex;
12364                 qboolean cullbox = false;
12365                 const q3mbrush_t *brush;
12366                 const bih_t *bih = &model->collision_bih;
12367                 const bih_leaf_t *bihleaf;
12368                 float vertex3f[3][3];
12369                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12370                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12371                 {
12372                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12373                                 continue;
12374                         switch (bihleaf->type)
12375                         {
12376                         case BIH_BRUSH:
12377                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12378                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12379                                 {
12380                                         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);
12381                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12382                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12383                                 }
12384                                 break;
12385                         case BIH_COLLISIONTRIANGLE:
12386                                 triangleindex = bihleaf->itemindex;
12387                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12388                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12389                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12390                                 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);
12391                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12392                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12393                                 break;
12394                         case BIH_RENDERTRIANGLE:
12395                                 triangleindex = bihleaf->itemindex;
12396                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12397                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12398                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12399                                 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);
12400                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12401                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12402                                 break;
12403                         }
12404                 }
12405         }
12406
12407         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12408
12409 #ifndef USE_GLES2
12410         if (r_showtris.integer && qglPolygonMode)
12411         {
12412                 if (r_showdisabledepthtest.integer)
12413                 {
12414                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12415                         GL_DepthMask(false);
12416                 }
12417                 else
12418                 {
12419                         GL_BlendFunc(GL_ONE, GL_ZERO);
12420                         GL_DepthMask(true);
12421                 }
12422                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12423                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12424                 {
12425                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12426                                 continue;
12427                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12428                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12429                         {
12430                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12431                                 if (!rsurface.texture->currentlayers->depthmask)
12432                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12433                                 else if (ent == r_refdef.scene.worldentity)
12434                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12435                                 else
12436                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12437                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12438                                 RSurf_DrawBatch();
12439                         }
12440                 }
12441                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12442                 rsurface.texture = NULL;
12443         }
12444
12445         if (r_shownormals.value != 0 && qglBegin)
12446         {
12447                 int l, k;
12448                 vec3_t v;
12449                 if (r_showdisabledepthtest.integer)
12450                 {
12451                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12452                         GL_DepthMask(false);
12453                 }
12454                 else
12455                 {
12456                         GL_BlendFunc(GL_ONE, GL_ZERO);
12457                         GL_DepthMask(true);
12458                 }
12459                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12460                 {
12461                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12462                                 continue;
12463                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12464                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12465                         {
12466                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12467                                 qglBegin(GL_LINES);
12468                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12469                                 {
12470                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12471                                         {
12472                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12473                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12474                                                 qglVertex3f(v[0], v[1], v[2]);
12475                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12476                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12477                                                 qglVertex3f(v[0], v[1], v[2]);
12478                                         }
12479                                 }
12480                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12481                                 {
12482                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12483                                         {
12484                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12485                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12486                                                 qglVertex3f(v[0], v[1], v[2]);
12487                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12488                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12489                                                 qglVertex3f(v[0], v[1], v[2]);
12490                                         }
12491                                 }
12492                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12493                                 {
12494                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12495                                         {
12496                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12497                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12498                                                 qglVertex3f(v[0], v[1], v[2]);
12499                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12500                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12501                                                 qglVertex3f(v[0], v[1], v[2]);
12502                                         }
12503                                 }
12504                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12505                                 {
12506                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12507                                         {
12508                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12509                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12510                                                 qglVertex3f(v[0], v[1], v[2]);
12511                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12512                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12513                                                 qglVertex3f(v[0], v[1], v[2]);
12514                                         }
12515                                 }
12516                                 qglEnd();
12517                                 CHECKGLERROR
12518                         }
12519                 }
12520                 rsurface.texture = NULL;
12521         }
12522 #endif
12523 }
12524
12525 int r_maxsurfacelist = 0;
12526 const msurface_t **r_surfacelist = NULL;
12527 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12528 {
12529         int i, j, endj, flagsmask;
12530         dp_model_t *model = r_refdef.scene.worldmodel;
12531         msurface_t *surfaces;
12532         unsigned char *update;
12533         int numsurfacelist = 0;
12534         if (model == NULL)
12535                 return;
12536
12537         if (r_maxsurfacelist < model->num_surfaces)
12538         {
12539                 r_maxsurfacelist = model->num_surfaces;
12540                 if (r_surfacelist)
12541                         Mem_Free((msurface_t**)r_surfacelist);
12542                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12543         }
12544
12545         RSurf_ActiveWorldEntity();
12546
12547         surfaces = model->data_surfaces;
12548         update = model->brushq1.lightmapupdateflags;
12549
12550         // update light styles on this submodel
12551         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12552         {
12553                 model_brush_lightstyleinfo_t *style;
12554                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12555                 {
12556                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12557                         {
12558                                 int *list = style->surfacelist;
12559                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12560                                 for (j = 0;j < style->numsurfaces;j++)
12561                                         update[list[j]] = true;
12562                         }
12563                 }
12564         }
12565
12566         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12567
12568         if (debug)
12569         {
12570                 R_DrawDebugModel();
12571                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12572                 return;
12573         }
12574
12575         rsurface.lightmaptexture = NULL;
12576         rsurface.deluxemaptexture = NULL;
12577         rsurface.uselightmaptexture = false;
12578         rsurface.texture = NULL;
12579         rsurface.rtlight = NULL;
12580         numsurfacelist = 0;
12581         // add visible surfaces to draw list
12582         for (i = 0;i < model->nummodelsurfaces;i++)
12583         {
12584                 j = model->sortedmodelsurfaces[i];
12585                 if (r_refdef.viewcache.world_surfacevisible[j])
12586                         r_surfacelist[numsurfacelist++] = surfaces + j;
12587         }
12588         // update lightmaps if needed
12589         if (model->brushq1.firstrender)
12590         {
12591                 model->brushq1.firstrender = false;
12592                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12593                         if (update[j])
12594                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12595         }
12596         else if (update)
12597         {
12598                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12599                         if (r_refdef.viewcache.world_surfacevisible[j])
12600                                 if (update[j])
12601                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12602         }
12603         // don't do anything if there were no surfaces
12604         if (!numsurfacelist)
12605         {
12606                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12607                 return;
12608         }
12609         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12610
12611         // add to stats if desired
12612         if (r_speeds.integer && !skysurfaces && !depthonly)
12613         {
12614                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12615                 for (j = 0;j < numsurfacelist;j++)
12616                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12617         }
12618
12619         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12620 }
12621
12622 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12623 {
12624         int i, j, endj, flagsmask;
12625         dp_model_t *model = ent->model;
12626         msurface_t *surfaces;
12627         unsigned char *update;
12628         int numsurfacelist = 0;
12629         if (model == NULL)
12630                 return;
12631
12632         if (r_maxsurfacelist < model->num_surfaces)
12633         {
12634                 r_maxsurfacelist = model->num_surfaces;
12635                 if (r_surfacelist)
12636                         Mem_Free((msurface_t **)r_surfacelist);
12637                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12638         }
12639
12640         // if the model is static it doesn't matter what value we give for
12641         // wantnormals and wanttangents, so this logic uses only rules applicable
12642         // to a model, knowing that they are meaningless otherwise
12643         if (ent == r_refdef.scene.worldentity)
12644                 RSurf_ActiveWorldEntity();
12645         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12646                 RSurf_ActiveModelEntity(ent, false, false, false);
12647         else if (prepass)
12648                 RSurf_ActiveModelEntity(ent, true, true, true);
12649         else if (depthonly)
12650         {
12651                 switch (vid.renderpath)
12652                 {
12653                 case RENDERPATH_GL20:
12654                 case RENDERPATH_D3D9:
12655                 case RENDERPATH_D3D10:
12656                 case RENDERPATH_D3D11:
12657                 case RENDERPATH_SOFT:
12658                 case RENDERPATH_GLES2:
12659                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12660                         break;
12661                 case RENDERPATH_GL11:
12662                 case RENDERPATH_GL13:
12663                 case RENDERPATH_GLES1:
12664                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12665                         break;
12666                 }
12667         }
12668         else
12669         {
12670                 switch (vid.renderpath)
12671                 {
12672                 case RENDERPATH_GL20:
12673                 case RENDERPATH_D3D9:
12674                 case RENDERPATH_D3D10:
12675                 case RENDERPATH_D3D11:
12676                 case RENDERPATH_SOFT:
12677                 case RENDERPATH_GLES2:
12678                         RSurf_ActiveModelEntity(ent, true, true, false);
12679                         break;
12680                 case RENDERPATH_GL11:
12681                 case RENDERPATH_GL13:
12682                 case RENDERPATH_GLES1:
12683                         RSurf_ActiveModelEntity(ent, true, false, false);
12684                         break;
12685                 }
12686         }
12687
12688         surfaces = model->data_surfaces;
12689         update = model->brushq1.lightmapupdateflags;
12690
12691         // update light styles
12692         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12693         {
12694                 model_brush_lightstyleinfo_t *style;
12695                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12696                 {
12697                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12698                         {
12699                                 int *list = style->surfacelist;
12700                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12701                                 for (j = 0;j < style->numsurfaces;j++)
12702                                         update[list[j]] = true;
12703                         }
12704                 }
12705         }
12706
12707         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12708
12709         if (debug)
12710         {
12711                 R_DrawDebugModel();
12712                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12713                 return;
12714         }
12715
12716         rsurface.lightmaptexture = NULL;
12717         rsurface.deluxemaptexture = NULL;
12718         rsurface.uselightmaptexture = false;
12719         rsurface.texture = NULL;
12720         rsurface.rtlight = NULL;
12721         numsurfacelist = 0;
12722         // add visible surfaces to draw list
12723         for (i = 0;i < model->nummodelsurfaces;i++)
12724                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12725         // don't do anything if there were no surfaces
12726         if (!numsurfacelist)
12727         {
12728                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12729                 return;
12730         }
12731         // update lightmaps if needed
12732         if (update)
12733         {
12734                 int updated = 0;
12735                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12736                 {
12737                         if (update[j])
12738                         {
12739                                 updated++;
12740                                 R_BuildLightMap(ent, surfaces + j);
12741                         }
12742                 }
12743         }
12744
12745         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12746
12747         // add to stats if desired
12748         if (r_speeds.integer && !skysurfaces && !depthonly)
12749         {
12750                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12751                 for (j = 0;j < numsurfacelist;j++)
12752                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12753         }
12754
12755         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12756 }
12757
12758 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12759 {
12760         static texture_t texture;
12761         static msurface_t surface;
12762         const msurface_t *surfacelist = &surface;
12763
12764         // fake enough texture and surface state to render this geometry
12765
12766         texture.update_lastrenderframe = -1; // regenerate this texture
12767         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12768         texture.basealpha = 1.0f;
12769         texture.currentskinframe = skinframe;
12770         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12771         texture.offsetmapping = OFFSETMAPPING_OFF;
12772         texture.offsetscale = 1;
12773         texture.specularscalemod = 1;
12774         texture.specularpowermod = 1;
12775         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12776         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12777         // JUST GREP FOR "specularscalemod = 1".
12778
12779         surface.texture = &texture;
12780         surface.num_triangles = numtriangles;
12781         surface.num_firsttriangle = firsttriangle;
12782         surface.num_vertices = numvertices;
12783         surface.num_firstvertex = firstvertex;
12784
12785         // now render it
12786         rsurface.texture = R_GetCurrentTexture(surface.texture);
12787         rsurface.lightmaptexture = NULL;
12788         rsurface.deluxemaptexture = NULL;
12789         rsurface.uselightmaptexture = false;
12790         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12791 }
12792
12793 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)
12794 {
12795         static msurface_t surface;
12796         const msurface_t *surfacelist = &surface;
12797
12798         // fake enough texture and surface state to render this geometry
12799         surface.texture = texture;
12800         surface.num_triangles = numtriangles;
12801         surface.num_firsttriangle = firsttriangle;
12802         surface.num_vertices = numvertices;
12803         surface.num_firstvertex = firstvertex;
12804
12805         // now render it
12806         rsurface.texture = R_GetCurrentTexture(surface.texture);
12807         rsurface.lightmaptexture = NULL;
12808         rsurface.deluxemaptexture = NULL;
12809         rsurface.uselightmaptexture = false;
12810         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12811 }