]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
changed default r_viewscale_fpsscaling_min from 0.25 (25% pixels, 50%
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 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"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 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)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 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"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 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)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 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)"};
91 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)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 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."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 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."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 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"};
114 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"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 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"};
121
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130
131 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)"};
132 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"};
133
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 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"};
145 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"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 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"};
149 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)"};
150 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)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 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)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 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)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 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)"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168
169 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)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 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"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
175
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
180
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
188
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
199
200 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"};
201
202 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"};
203
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
205
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
215
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 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"};
218
219 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."};
220
221 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)"};
222
223 extern cvar_t v_glslgamma;
224
225 extern qboolean v_flipped_state;
226
227 static struct r_bloomstate_s
228 {
229         qboolean enabled;
230         qboolean hdr;
231
232         int bloomwidth, bloomheight;
233
234         textype_t texturetype;
235         int viewfbo; // used to check if r_viewfbo cvar has changed
236
237         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240
241         int screentexturewidth, screentextureheight;
242         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243
244         int bloomtexturewidth, bloomtextureheight;
245         rtexture_t *texture_bloom;
246
247         // arrays for rendering the screen passes
248         float screentexcoord2f[8];
249         float bloomtexcoord2f[8];
250         float offsettexcoord2f[8];
251
252         r_viewport_t viewport;
253 }
254 r_bloomstate;
255
256 r_waterstate_t r_waterstate;
257
258 /// shadow volume bsp struct with automatically growing nodes buffer
259 svbsp_t r_svbsp;
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 128; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
618 ;
619
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
622 ;
623
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
626
627 //=======================================================================================================================================================
628
629 typedef struct shaderpermutationinfo_s
630 {
631         const char *pretext;
632         const char *name;
633 }
634 shaderpermutationinfo_t;
635
636 typedef struct shadermodeinfo_s
637 {
638         const char *vertexfilename;
639         const char *geometryfilename;
640         const char *fragmentfilename;
641         const char *pretext;
642         const char *name;
643 }
644 shadermodeinfo_t;
645
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {
649         {"#define USEDIFFUSE\n", " diffuse"},
650         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651         {"#define USEVIEWTINT\n", " viewtint"},
652         {"#define USECOLORMAPPING\n", " colormapping"},
653         {"#define USESATURATION\n", " saturation"},
654         {"#define USEFOGINSIDE\n", " foginside"},
655         {"#define USEFOGOUTSIDE\n", " fogoutside"},
656         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658         {"#define USEGAMMARAMPS\n", " gammaramps"},
659         {"#define USECUBEFILTER\n", " cubefilter"},
660         {"#define USEGLOW\n", " glow"},
661         {"#define USEBLOOM\n", " bloom"},
662         {"#define USESPECULAR\n", " specular"},
663         {"#define USEPOSTPROCESSING\n", " postprocessing"},
664         {"#define USEREFLECTION\n", " reflection"},
665         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
679 };
680
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
703 {
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
720 };
721
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
724 {
725         /// hash lookup data
726         struct r_glsl_permutation_s *hashnext;
727         unsigned int mode;
728         unsigned int permutation;
729
730         /// indicates if we have tried compiling this permutation already
731         qboolean compiled;
732         /// 0 if compilation failed
733         int program;
734         // texture units assigned to each detected uniform
735         int tex_Texture_First;
736         int tex_Texture_Second;
737         int tex_Texture_GammaRamps;
738         int tex_Texture_Normal;
739         int tex_Texture_Color;
740         int tex_Texture_Gloss;
741         int tex_Texture_Glow;
742         int tex_Texture_SecondaryNormal;
743         int tex_Texture_SecondaryColor;
744         int tex_Texture_SecondaryGloss;
745         int tex_Texture_SecondaryGlow;
746         int tex_Texture_Pants;
747         int tex_Texture_Shirt;
748         int tex_Texture_FogHeightTexture;
749         int tex_Texture_FogMask;
750         int tex_Texture_Lightmap;
751         int tex_Texture_Deluxemap;
752         int tex_Texture_Attenuation;
753         int tex_Texture_Cube;
754         int tex_Texture_Refraction;
755         int tex_Texture_Reflection;
756         int tex_Texture_ShadowMap2D;
757         int tex_Texture_CubeProjection;
758         int tex_Texture_ScreenDepth;
759         int tex_Texture_ScreenNormalMap;
760         int tex_Texture_ScreenDiffuse;
761         int tex_Texture_ScreenSpecular;
762         int tex_Texture_ReflectMask;
763         int tex_Texture_ReflectCube;
764         int tex_Texture_BounceGrid;
765         /// locations of detected uniforms in program object, or -1 if not found
766         int loc_Texture_First;
767         int loc_Texture_Second;
768         int loc_Texture_GammaRamps;
769         int loc_Texture_Normal;
770         int loc_Texture_Color;
771         int loc_Texture_Gloss;
772         int loc_Texture_Glow;
773         int loc_Texture_SecondaryNormal;
774         int loc_Texture_SecondaryColor;
775         int loc_Texture_SecondaryGloss;
776         int loc_Texture_SecondaryGlow;
777         int loc_Texture_Pants;
778         int loc_Texture_Shirt;
779         int loc_Texture_FogHeightTexture;
780         int loc_Texture_FogMask;
781         int loc_Texture_Lightmap;
782         int loc_Texture_Deluxemap;
783         int loc_Texture_Attenuation;
784         int loc_Texture_Cube;
785         int loc_Texture_Refraction;
786         int loc_Texture_Reflection;
787         int loc_Texture_ShadowMap2D;
788         int loc_Texture_CubeProjection;
789         int loc_Texture_ScreenDepth;
790         int loc_Texture_ScreenNormalMap;
791         int loc_Texture_ScreenDiffuse;
792         int loc_Texture_ScreenSpecular;
793         int loc_Texture_ReflectMask;
794         int loc_Texture_ReflectCube;
795         int loc_Texture_BounceGrid;
796         int loc_Alpha;
797         int loc_BloomBlur_Parameters;
798         int loc_ClientTime;
799         int loc_Color_Ambient;
800         int loc_Color_Diffuse;
801         int loc_Color_Specular;
802         int loc_Color_Glow;
803         int loc_Color_Pants;
804         int loc_Color_Shirt;
805         int loc_DeferredColor_Ambient;
806         int loc_DeferredColor_Diffuse;
807         int loc_DeferredColor_Specular;
808         int loc_DeferredMod_Diffuse;
809         int loc_DeferredMod_Specular;
810         int loc_DistortScaleRefractReflect;
811         int loc_EyePosition;
812         int loc_FogColor;
813         int loc_FogHeightFade;
814         int loc_FogPlane;
815         int loc_FogPlaneViewDist;
816         int loc_FogRangeRecip;
817         int loc_LightColor;
818         int loc_LightDir;
819         int loc_LightPosition;
820         int loc_OffsetMapping_ScaleSteps;
821         int loc_PixelSize;
822         int loc_ReflectColor;
823         int loc_ReflectFactor;
824         int loc_ReflectOffset;
825         int loc_RefractColor;
826         int loc_Saturation;
827         int loc_ScreenCenterRefractReflect;
828         int loc_ScreenScaleRefractReflect;
829         int loc_ScreenToDepth;
830         int loc_ShadowMap_Parameters;
831         int loc_ShadowMap_TextureScale;
832         int loc_SpecularPower;
833         int loc_UserVec1;
834         int loc_UserVec2;
835         int loc_UserVec3;
836         int loc_UserVec4;
837         int loc_ViewTintColor;
838         int loc_ViewToLight;
839         int loc_ModelToLight;
840         int loc_TexMatrix;
841         int loc_BackgroundTexMatrix;
842         int loc_ModelViewProjectionMatrix;
843         int loc_ModelViewMatrix;
844         int loc_PixelToScreenTexCoord;
845         int loc_ModelToReflectCube;
846         int loc_ShadowMapMatrix;
847         int loc_BloomColorSubtract;
848         int loc_NormalmapScrollBlend;
849         int loc_BounceGridMatrix;
850         int loc_BounceGridIntensity;
851 }
852 r_glsl_permutation_t;
853
854 #define SHADERPERMUTATION_HASHSIZE 256
855
856
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
859 enum
860 {
861         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
867         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
868 };
869 #define SHADERSTATICPARMS_COUNT 7
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
877 {
878         static int r_compileshader_staticparms_save[1];
879         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
881
882         // detect all
883         if (r_glsl_saturation_redcompensate.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885         if (r_glsl_vertextextureblend_usebothalphas.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887         if (r_shadow_glossexact.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889         if (r_glsl_postprocess.integer)
890         {
891                 if (r_glsl_postprocess_uservec1_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893                 if (r_glsl_postprocess_uservec2_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895                 if (r_glsl_postprocess_uservec3_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897                 if (r_glsl_postprocess_uservec4_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
899         }
900         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
901 }
902
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
906         else \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
909 {
910         shaderstaticparms_count = 0;
911
912         // emit all
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920 }
921
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
928
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
930 {
931         //unsigned int hashdepth = 0;
932         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933         r_glsl_permutation_t *p;
934         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
935         {
936                 if (p->mode == mode && p->permutation == permutation)
937                 {
938                         //if (hashdepth > 10)
939                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
940                         return p;
941                 }
942                 //hashdepth++;
943         }
944         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
945         p->mode = mode;
946         p->permutation = permutation;
947         p->hashnext = r_glsl_permutationhash[mode][hashindex];
948         r_glsl_permutationhash[mode][hashindex] = p;
949         //if (hashdepth > 10)
950         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
951         return p;
952 }
953
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
955 {
956         char *shaderstring;
957         if (!filename || !filename[0])
958                 return NULL;
959         if (!strcmp(filename, "glsl/default.glsl"))
960         {
961                 if (!glslshaderstring)
962                 {
963                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964                         if (glslshaderstring)
965                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
966                         else
967                                 glslshaderstring = (char *)builtinshaderstring;
968                 }
969                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
971                 return shaderstring;
972         }
973         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
974         if (shaderstring)
975         {
976                 if (printfromdisknotice)
977                         Con_DPrintf("from disk %s... ", filename);
978                 return shaderstring;
979         }
980         return shaderstring;
981 }
982
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
984 {
985         int i;
986         int sampler;
987         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988         char *vertexstring, *geometrystring, *fragmentstring;
989         char permutationname[256];
990         int vertstrings_count = 0;
991         int geomstrings_count = 0;
992         int fragstrings_count = 0;
993         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996
997         if (p->compiled)
998                 return;
999         p->compiled = true;
1000         p->program = 0;
1001
1002         permutationname[0] = 0;
1003         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1006
1007         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1008
1009         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010         if(vid.support.gl20shaders130)
1011         {
1012                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1018         }
1019
1020         // the first pretext is which type of shader to compile as
1021         // (later these will all be bound together as a program object)
1022         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1025
1026         // the second pretext is the mode (for example a light source)
1027         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1031
1032         // now add all the permutation pretexts
1033         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1034         {
1035                 if (permutation & (1<<i))
1036                 {
1037                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1041                 }
1042                 else
1043                 {
1044                         // keep line numbers correct
1045                         vertstrings_list[vertstrings_count++] = "\n";
1046                         geomstrings_list[geomstrings_count++] = "\n";
1047                         fragstrings_list[fragstrings_count++] = "\n";
1048                 }
1049         }
1050
1051         // add static parms
1052         R_CompileShader_AddStaticParms(mode, permutation);
1053         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         vertstrings_count += shaderstaticparms_count;
1055         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         geomstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         fragstrings_count += shaderstaticparms_count;
1059
1060         // now append the shader text itself
1061         vertstrings_list[vertstrings_count++] = vertexstring;
1062         geomstrings_list[geomstrings_count++] = geometrystring;
1063         fragstrings_list[fragstrings_count++] = fragmentstring;
1064
1065         // if any sources were NULL, clear the respective list
1066         if (!vertexstring)
1067                 vertstrings_count = 0;
1068         if (!geometrystring)
1069                 geomstrings_count = 0;
1070         if (!fragmentstring)
1071                 fragstrings_count = 0;
1072
1073         // compile the shader program
1074         if (vertstrings_count + geomstrings_count + fragstrings_count)
1075                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1076         if (p->program)
1077         {
1078                 CHECKGLERROR
1079                 qglUseProgram(p->program);CHECKGLERROR
1080                 // look up all the uniform variable names we care about, so we don't
1081                 // have to look them up every time we set them
1082
1083                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1084                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1085                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1087                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1088                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1089                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1090                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1095                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1096                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1098                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1102                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1103                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1104                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1114                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1116                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1117                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1118                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1119                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1120                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1121                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1122                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1129                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1130                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1131                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1132                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1134                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1135                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1136                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1137                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1139                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1140                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1141                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1142                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1143                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1144                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1147                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1150                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1151                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1152                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1153                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1154                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1155                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1156                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1157                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1158                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168                 // initialize the samplers to refer to the texture units we use
1169                 p->tex_Texture_First = -1;
1170                 p->tex_Texture_Second = -1;
1171                 p->tex_Texture_GammaRamps = -1;
1172                 p->tex_Texture_Normal = -1;
1173                 p->tex_Texture_Color = -1;
1174                 p->tex_Texture_Gloss = -1;
1175                 p->tex_Texture_Glow = -1;
1176                 p->tex_Texture_SecondaryNormal = -1;
1177                 p->tex_Texture_SecondaryColor = -1;
1178                 p->tex_Texture_SecondaryGloss = -1;
1179                 p->tex_Texture_SecondaryGlow = -1;
1180                 p->tex_Texture_Pants = -1;
1181                 p->tex_Texture_Shirt = -1;
1182                 p->tex_Texture_FogHeightTexture = -1;
1183                 p->tex_Texture_FogMask = -1;
1184                 p->tex_Texture_Lightmap = -1;
1185                 p->tex_Texture_Deluxemap = -1;
1186                 p->tex_Texture_Attenuation = -1;
1187                 p->tex_Texture_Cube = -1;
1188                 p->tex_Texture_Refraction = -1;
1189                 p->tex_Texture_Reflection = -1;
1190                 p->tex_Texture_ShadowMap2D = -1;
1191                 p->tex_Texture_CubeProjection = -1;
1192                 p->tex_Texture_ScreenDepth = -1;
1193                 p->tex_Texture_ScreenNormalMap = -1;
1194                 p->tex_Texture_ScreenDiffuse = -1;
1195                 p->tex_Texture_ScreenSpecular = -1;
1196                 p->tex_Texture_ReflectMask = -1;
1197                 p->tex_Texture_ReflectCube = -1;
1198                 p->tex_Texture_BounceGrid = -1;
1199                 sampler = 0;
1200                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1201                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1202                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1203                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1204                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1205                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1206                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1207                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1211                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1212                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1213                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1215                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1216                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1217                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1218                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1219                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1220                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1221                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1222                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1223                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1227                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1229                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1230                 CHECKGLERROR
1231                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1232         }
1233         else
1234                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1235
1236         // free the strings
1237         if (vertexstring)
1238                 Mem_Free(vertexstring);
1239         if (geometrystring)
1240                 Mem_Free(geometrystring);
1241         if (fragmentstring)
1242                 Mem_Free(fragmentstring);
1243 }
1244
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1246 {
1247         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248         if (r_glsl_permutation != perm)
1249         {
1250                 r_glsl_permutation = perm;
1251                 if (!r_glsl_permutation->program)
1252                 {
1253                         if (!r_glsl_permutation->compiled)
1254                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1255                         if (!r_glsl_permutation->program)
1256                         {
1257                                 // remove features until we find a valid permutation
1258                                 int i;
1259                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1260                                 {
1261                                         // reduce i more quickly whenever it would not remove any bits
1262                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263                                         if (!(permutation & j))
1264                                                 continue;
1265                                         permutation -= j;
1266                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267                                         if (!r_glsl_permutation->compiled)
1268                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                                         if (r_glsl_permutation->program)
1270                                                 break;
1271                                 }
1272                                 if (i >= SHADERPERMUTATION_COUNT)
1273                                 {
1274                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276                                         qglUseProgram(0);CHECKGLERROR
1277                                         return; // no bit left to clear, entire mode is broken
1278                                 }
1279                         }
1280                 }
1281                 CHECKGLERROR
1282                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1283         }
1284         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 }
1288
1289 #ifdef SUPPORTD3D
1290
1291 #ifdef SUPPORTD3D
1292 #include <d3d9.h>
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1295 #endif
1296
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1299 {
1300         /// hash lookup data
1301         struct r_hlsl_permutation_s *hashnext;
1302         unsigned int mode;
1303         unsigned int permutation;
1304
1305         /// indicates if we have tried compiling this permutation already
1306         qboolean compiled;
1307         /// NULL if compilation failed
1308         IDirect3DVertexShader9 *vertexshader;
1309         IDirect3DPixelShader9 *pixelshader;
1310 }
1311 r_hlsl_permutation_t;
1312
1313 typedef enum D3DVSREGISTER_e
1314 {
1315         D3DVSREGISTER_TexMatrix = 0, // float4x4
1316         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320         D3DVSREGISTER_ModelToLight = 20, // float4x4
1321         D3DVSREGISTER_EyePosition = 24,
1322         D3DVSREGISTER_FogPlane = 25,
1323         D3DVSREGISTER_LightDir = 26,
1324         D3DVSREGISTER_LightPosition = 27,
1325 }
1326 D3DVSREGISTER_t;
1327
1328 typedef enum D3DPSREGISTER_e
1329 {
1330         D3DPSREGISTER_Alpha = 0,
1331         D3DPSREGISTER_BloomBlur_Parameters = 1,
1332         D3DPSREGISTER_ClientTime = 2,
1333         D3DPSREGISTER_Color_Ambient = 3,
1334         D3DPSREGISTER_Color_Diffuse = 4,
1335         D3DPSREGISTER_Color_Specular = 5,
1336         D3DPSREGISTER_Color_Glow = 6,
1337         D3DPSREGISTER_Color_Pants = 7,
1338         D3DPSREGISTER_Color_Shirt = 8,
1339         D3DPSREGISTER_DeferredColor_Ambient = 9,
1340         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341         D3DPSREGISTER_DeferredColor_Specular = 11,
1342         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343         D3DPSREGISTER_DeferredMod_Specular = 13,
1344         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345         D3DPSREGISTER_EyePosition = 15, // unused
1346         D3DPSREGISTER_FogColor = 16,
1347         D3DPSREGISTER_FogHeightFade = 17,
1348         D3DPSREGISTER_FogPlane = 18,
1349         D3DPSREGISTER_FogPlaneViewDist = 19,
1350         D3DPSREGISTER_FogRangeRecip = 20,
1351         D3DPSREGISTER_LightColor = 21,
1352         D3DPSREGISTER_LightDir = 22, // unused
1353         D3DPSREGISTER_LightPosition = 23,
1354         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355         D3DPSREGISTER_PixelSize = 25,
1356         D3DPSREGISTER_ReflectColor = 26,
1357         D3DPSREGISTER_ReflectFactor = 27,
1358         D3DPSREGISTER_ReflectOffset = 28,
1359         D3DPSREGISTER_RefractColor = 29,
1360         D3DPSREGISTER_Saturation = 30,
1361         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363         D3DPSREGISTER_ScreenToDepth = 33,
1364         D3DPSREGISTER_ShadowMap_Parameters = 34,
1365         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366         D3DPSREGISTER_SpecularPower = 36,
1367         D3DPSREGISTER_UserVec1 = 37,
1368         D3DPSREGISTER_UserVec2 = 38,
1369         D3DPSREGISTER_UserVec3 = 39,
1370         D3DPSREGISTER_UserVec4 = 40,
1371         D3DPSREGISTER_ViewTintColor = 41,
1372         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373         D3DPSREGISTER_BloomColorSubtract = 43,
1374         D3DPSREGISTER_ViewToLight = 44, // float4x4
1375         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376         D3DPSREGISTER_NormalmapScrollBlend = 52,
1377         // next at 53
1378 }
1379 D3DPSREGISTER_t;
1380
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1387
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1389 {
1390         //unsigned int hashdepth = 0;
1391         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392         r_hlsl_permutation_t *p;
1393         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1394         {
1395                 if (p->mode == mode && p->permutation == permutation)
1396                 {
1397                         //if (hashdepth > 10)
1398                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1399                         return p;
1400                 }
1401                 //hashdepth++;
1402         }
1403         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1404         p->mode = mode;
1405         p->permutation = permutation;
1406         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407         r_hlsl_permutationhash[mode][hashindex] = p;
1408         //if (hashdepth > 10)
1409         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1410         return p;
1411 }
1412
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1414 {
1415         char *shaderstring;
1416         if (!filename || !filename[0])
1417                 return NULL;
1418         if (!strcmp(filename, "hlsl/default.hlsl"))
1419         {
1420                 if (!hlslshaderstring)
1421                 {
1422                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423                         if (hlslshaderstring)
1424                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1425                         else
1426                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1427                 }
1428                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430                 return shaderstring;
1431         }
1432         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1433         if (shaderstring)
1434         {
1435                 if (printfromdisknotice)
1436                         Con_DPrintf("from disk %s... ", filename);
1437                 return shaderstring;
1438         }
1439         return shaderstring;
1440 }
1441
1442 #include <d3dx9.h>
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1445
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1447 {
1448         DWORD *vsbin = NULL;
1449         DWORD *psbin = NULL;
1450         fs_offset_t vsbinsize;
1451         fs_offset_t psbinsize;
1452 //      IDirect3DVertexShader9 *vs = NULL;
1453 //      IDirect3DPixelShader9 *ps = NULL;
1454         ID3DXBuffer *vslog = NULL;
1455         ID3DXBuffer *vsbuffer = NULL;
1456         ID3DXConstantTable *vsconstanttable = NULL;
1457         ID3DXBuffer *pslog = NULL;
1458         ID3DXBuffer *psbuffer = NULL;
1459         ID3DXConstantTable *psconstanttable = NULL;
1460         int vsresult = 0;
1461         int psresult = 0;
1462         char temp[MAX_INPUTLINE];
1463         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464         qboolean debugshader = gl_paranoid.integer != 0;
1465         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (!debugshader)
1468         {
1469                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1471         }
1472         if ((!vsbin && vertstring) || (!psbin && fragstring))
1473         {
1474                 const char* dllnames_d3dx9 [] =
1475                 {
1476                         "d3dx9_43.dll",
1477                         "d3dx9_42.dll",
1478                         "d3dx9_41.dll",
1479                         "d3dx9_40.dll",
1480                         "d3dx9_39.dll",
1481                         "d3dx9_38.dll",
1482                         "d3dx9_37.dll",
1483                         "d3dx9_36.dll",
1484                         "d3dx9_35.dll",
1485                         "d3dx9_34.dll",
1486                         "d3dx9_33.dll",
1487                         "d3dx9_32.dll",
1488                         "d3dx9_31.dll",
1489                         "d3dx9_30.dll",
1490                         "d3dx9_29.dll",
1491                         "d3dx9_28.dll",
1492                         "d3dx9_27.dll",
1493                         "d3dx9_26.dll",
1494                         "d3dx9_25.dll",
1495                         "d3dx9_24.dll",
1496                         NULL
1497                 };
1498                 dllhandle_t d3dx9_dll = NULL;
1499                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 dllfunction_t d3dx9_dllfuncs[] =
1503                 {
1504                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1505                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1506                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1507                         {NULL, NULL}
1508                 };
1509                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1510                 {
1511                         DWORD shaderflags = 0;
1512                         if (debugshader)
1513                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516                         if (vertstring && vertstring[0])
1517                         {
1518                                 if (debugshader)
1519                                 {
1520 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524                                 }
1525                                 else
1526                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527                                 if (vsbuffer)
1528                                 {
1529                                         vsbinsize = vsbuffer->GetBufferSize();
1530                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532                                         vsbuffer->Release();
1533                                 }
1534                                 if (vslog)
1535                                 {
1536                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1538                                         vslog->Release();
1539                                 }
1540                         }
1541                         if (fragstring && fragstring[0])
1542                         {
1543                                 if (debugshader)
1544                                 {
1545 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549                                 }
1550                                 else
1551                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552                                 if (psbuffer)
1553                                 {
1554                                         psbinsize = psbuffer->GetBufferSize();
1555                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557                                         psbuffer->Release();
1558                                 }
1559                                 if (pslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         pslog->Release();
1564                                 }
1565                         }
1566                         Sys_UnloadLibrary(&d3dx9_dll);
1567                 }
1568                 else
1569                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1570         }
1571         if (vsbin && psbin)
1572         {
1573                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574                 if (FAILED(vsresult))
1575                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577                 if (FAILED(psresult))
1578                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1579         }
1580         // free the shader data
1581         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1583 }
1584
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1586 {
1587         int i;
1588         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589         int vertstring_length = 0;
1590         int geomstring_length = 0;
1591         int fragstring_length = 0;
1592         char *t;
1593         char *vertexstring, *geometrystring, *fragmentstring;
1594         char *vertstring, *geomstring, *fragstring;
1595         char permutationname[256];
1596         char cachename[256];
1597         int vertstrings_count = 0;
1598         int geomstrings_count = 0;
1599         int fragstrings_count = 0;
1600         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603
1604         if (p->compiled)
1605                 return;
1606         p->compiled = true;
1607         p->vertexshader = NULL;
1608         p->pixelshader = NULL;
1609
1610         permutationname[0] = 0;
1611         cachename[0] = 0;
1612         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1615
1616         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617         strlcat(cachename, "hlsl/", sizeof(cachename));
1618
1619         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620         vertstrings_count = 0;
1621         geomstrings_count = 0;
1622         fragstrings_count = 0;
1623         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1626
1627         // the first pretext is which type of shader to compile as
1628         // (later these will all be bound together as a program object)
1629         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1632
1633         // the second pretext is the mode (for example a light source)
1634         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638         strlcat(cachename, modeinfo->name, sizeof(cachename));
1639
1640         // now add all the permutation pretexts
1641         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1642         {
1643                 if (permutation & (1<<i))
1644                 {
1645                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1650                 }
1651                 else
1652                 {
1653                         // keep line numbers correct
1654                         vertstrings_list[vertstrings_count++] = "\n";
1655                         geomstrings_list[geomstrings_count++] = "\n";
1656                         fragstrings_list[fragstrings_count++] = "\n";
1657                 }
1658         }
1659
1660         // add static parms
1661         R_CompileShader_AddStaticParms(mode, permutation);
1662         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         vertstrings_count += shaderstaticparms_count;
1664         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         geomstrings_count += shaderstaticparms_count;
1666         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         fragstrings_count += shaderstaticparms_count;
1668
1669         // replace spaces in the cachename with _ characters
1670         for (i = 0;cachename[i];i++)
1671                 if (cachename[i] == ' ')
1672                         cachename[i] = '_';
1673
1674         // now append the shader text itself
1675         vertstrings_list[vertstrings_count++] = vertexstring;
1676         geomstrings_list[geomstrings_count++] = geometrystring;
1677         fragstrings_list[fragstrings_count++] = fragmentstring;
1678
1679         // if any sources were NULL, clear the respective list
1680         if (!vertexstring)
1681                 vertstrings_count = 0;
1682         if (!geometrystring)
1683                 geomstrings_count = 0;
1684         if (!fragmentstring)
1685                 fragstrings_count = 0;
1686
1687         vertstring_length = 0;
1688         for (i = 0;i < vertstrings_count;i++)
1689                 vertstring_length += strlen(vertstrings_list[i]);
1690         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1693
1694         geomstring_length = 0;
1695         for (i = 0;i < geomstrings_count;i++)
1696                 geomstring_length += strlen(geomstrings_list[i]);
1697         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1700
1701         fragstring_length = 0;
1702         for (i = 0;i < fragstrings_count;i++)
1703                 fragstring_length += strlen(fragstrings_list[i]);
1704         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1707
1708         // try to load the cached shader, or generate one
1709         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1710
1711         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1713         else
1714                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1715
1716         // free the strings
1717         if (vertstring)
1718                 Mem_Free(vertstring);
1719         if (geomstring)
1720                 Mem_Free(geomstring);
1721         if (fragstring)
1722                 Mem_Free(fragstring);
1723         if (vertexstring)
1724                 Mem_Free(vertexstring);
1725         if (geometrystring)
1726                 Mem_Free(geometrystring);
1727         if (fragmentstring)
1728                 Mem_Free(fragmentstring);
1729 }
1730
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1737
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1744
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1746 {
1747         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748         if (r_hlsl_permutation != perm)
1749         {
1750                 r_hlsl_permutation = perm;
1751                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                 {
1753                         if (!r_hlsl_permutation->compiled)
1754                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1755                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                         {
1757                                 // remove features until we find a valid permutation
1758                                 int i;
1759                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1760                                 {
1761                                         // reduce i more quickly whenever it would not remove any bits
1762                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763                                         if (!(permutation & j))
1764                                                 continue;
1765                                         permutation -= j;
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         if (!r_hlsl_permutation->compiled)
1768                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1769                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1770                                                 break;
1771                                 }
1772                                 if (i >= SHADERPERMUTATION_COUNT)
1773                                 {
1774                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776                                         return; // no bit left to clear, entire mode is broken
1777                                 }
1778                         }
1779                 }
1780                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1782         }
1783         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1786 }
1787 #endif
1788
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1790 {
1791         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1795 }
1796
1797 void R_GLSL_Restart_f(void)
1798 {
1799         unsigned int i, limit;
1800         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801                 Mem_Free(glslshaderstring);
1802         glslshaderstring = NULL;
1803         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804                 Mem_Free(hlslshaderstring);
1805         hlslshaderstring = NULL;
1806         switch(vid.renderpath)
1807         {
1808         case RENDERPATH_D3D9:
1809 #ifdef SUPPORTD3D
1810                 {
1811                         r_hlsl_permutation_t *p;
1812                         r_hlsl_permutation = NULL;
1813                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814                         for (i = 0;i < limit;i++)
1815                         {
1816                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1817                                 {
1818                                         if (p->vertexshader)
1819                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1820                                         if (p->pixelshader)
1821                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1822                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1823                                 }
1824                         }
1825                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1826                 }
1827 #endif
1828                 break;
1829         case RENDERPATH_D3D10:
1830                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1831                 break;
1832         case RENDERPATH_D3D11:
1833                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834                 break;
1835         case RENDERPATH_GL20:
1836         case RENDERPATH_GLES2:
1837                 {
1838                         r_glsl_permutation_t *p;
1839                         r_glsl_permutation = NULL;
1840                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841                         for (i = 0;i < limit;i++)
1842                         {
1843                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1844                                 {
1845                                         GL_Backend_FreeProgram(p->program);
1846                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1847                                 }
1848                         }
1849                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1850                 }
1851                 break;
1852         case RENDERPATH_GL13:
1853         case RENDERPATH_GL11:
1854                 break;
1855         case RENDERPATH_SOFT:
1856                 break;
1857         }
1858 }
1859
1860 void R_GLSL_DumpShader_f(void)
1861 {
1862         int i;
1863         qfile_t *file;
1864
1865         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1866         if (file)
1867         {
1868                 FS_Print(file, "/* The engine may define the following macros:\n");
1869                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870                 for (i = 0;i < SHADERMODE_COUNT;i++)
1871                         FS_Print(file, glslshadermodeinfo[i].pretext);
1872                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873                         FS_Print(file, shaderpermutationinfo[i].pretext);
1874                 FS_Print(file, "*/\n");
1875                 FS_Print(file, builtinshaderstring);
1876                 FS_Close(file);
1877                 Con_Printf("glsl/default.glsl written\n");
1878         }
1879         else
1880                 Con_Printf("failed to write to glsl/default.glsl\n");
1881
1882         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1883         if (file)
1884         {
1885                 FS_Print(file, "/* The engine may define the following macros:\n");
1886                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887                 for (i = 0;i < SHADERMODE_COUNT;i++)
1888                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1889                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890                         FS_Print(file, shaderpermutationinfo[i].pretext);
1891                 FS_Print(file, "*/\n");
1892                 FS_Print(file, builtinhlslshaderstring);
1893                 FS_Close(file);
1894                 Con_Printf("hlsl/default.hlsl written\n");
1895         }
1896         else
1897                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1898 }
1899
1900 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1901 {
1902         if (!second)
1903                 texturemode = GL_MODULATE;
1904         switch (vid.renderpath)
1905         {
1906         case RENDERPATH_D3D9:
1907 #ifdef SUPPORTD3D
1908                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1909                 R_Mesh_TexBind(GL20TU_FIRST , first );
1910                 R_Mesh_TexBind(GL20TU_SECOND, second);
1911 #endif
1912                 break;
1913         case RENDERPATH_D3D10:
1914                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1915                 break;
1916         case RENDERPATH_D3D11:
1917                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918                 break;
1919         case RENDERPATH_GL20:
1920         case RENDERPATH_GLES2:
1921                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1922                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1923                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1924                 break;
1925         case RENDERPATH_GL13:
1926                 R_Mesh_TexBind(0, first );
1927                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1928                 R_Mesh_TexBind(1, second);
1929                 if (second)
1930                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1931                 break;
1932         case RENDERPATH_GL11:
1933                 R_Mesh_TexBind(0, first );
1934                 break;
1935         case RENDERPATH_SOFT:
1936                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1937                 R_Mesh_TexBind(GL20TU_FIRST , first );
1938                 R_Mesh_TexBind(GL20TU_SECOND, second);
1939                 break;
1940         }
1941 }
1942
1943 void R_SetupShader_DepthOrShadow(void)
1944 {
1945         switch (vid.renderpath)
1946         {
1947         case RENDERPATH_D3D9:
1948 #ifdef SUPPORTD3D
1949                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1950 #endif
1951                 break;
1952         case RENDERPATH_D3D10:
1953                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954                 break;
1955         case RENDERPATH_D3D11:
1956                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_GL20:
1959         case RENDERPATH_GLES2:
1960                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1961                 break;
1962         case RENDERPATH_GL13:
1963                 R_Mesh_TexBind(0, 0);
1964                 R_Mesh_TexBind(1, 0);
1965                 break;
1966         case RENDERPATH_GL11:
1967                 R_Mesh_TexBind(0, 0);
1968                 break;
1969         case RENDERPATH_SOFT:
1970                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1971                 break;
1972         }
1973 }
1974
1975 void R_SetupShader_ShowDepth(void)
1976 {
1977         switch (vid.renderpath)
1978         {
1979         case RENDERPATH_D3D9:
1980 #ifdef SUPPORTHLSL
1981                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1982 #endif
1983                 break;
1984         case RENDERPATH_D3D10:
1985                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_D3D11:
1988                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                 break;
1990         case RENDERPATH_GL20:
1991         case RENDERPATH_GLES2:
1992                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1993                 break;
1994         case RENDERPATH_GL13:
1995                 break;
1996         case RENDERPATH_GL11:
1997                 break;
1998         case RENDERPATH_SOFT:
1999                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2000                 break;
2001         }
2002 }
2003
2004 extern qboolean r_shadow_usingdeferredprepass;
2005 extern cvar_t r_shadow_deferred_8bitrange;
2006 extern rtexture_t *r_shadow_attenuationgradienttexture;
2007 extern rtexture_t *r_shadow_attenuation2dtexture;
2008 extern rtexture_t *r_shadow_attenuation3dtexture;
2009 extern qboolean r_shadow_usingshadowmap2d;
2010 extern qboolean r_shadow_usingshadowmaportho;
2011 extern float r_shadow_shadowmap_texturescale[2];
2012 extern float r_shadow_shadowmap_parameters[4];
2013 extern qboolean r_shadow_shadowmapvsdct;
2014 extern qboolean r_shadow_shadowmapsampler;
2015 extern int r_shadow_shadowmappcf;
2016 extern rtexture_t *r_shadow_shadowmap2dtexture;
2017 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2018 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2019 extern matrix4x4_t r_shadow_shadowmapmatrix;
2020 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2021 extern int r_shadow_prepass_width;
2022 extern int r_shadow_prepass_height;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2024 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2026 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2027 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2028
2029 #define BLENDFUNC_ALLOWS_COLORMOD      1
2030 #define BLENDFUNC_ALLOWS_FOG           2
2031 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2032 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2033 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2034 static int R_BlendFuncFlags(int src, int dst)
2035 {
2036         int r = 0;
2037
2038         // a blendfunc allows colormod if:
2039         // a) it can never keep the destination pixel invariant, or
2040         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2041         // this is to prevent unintended side effects from colormod
2042
2043         // a blendfunc allows fog if:
2044         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2045         // this is to prevent unintended side effects from fog
2046
2047         // these checks are the output of fogeval.pl
2048
2049         r |= BLENDFUNC_ALLOWS_COLORMOD;
2050         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2054         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2059         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2060         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2061         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2070         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071
2072         return r;
2073 }
2074
2075 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)
2076 {
2077         // select a permutation of the lighting shader appropriate to this
2078         // combination of texture, entity, light source, and fogging, only use the
2079         // minimum features necessary to avoid wasting rendering time in the
2080         // fragment shader on features that are not being used
2081         unsigned int permutation = 0;
2082         unsigned int mode = 0;
2083         int blendfuncflags;
2084         static float dummy_colormod[3] = {1, 1, 1};
2085         float *colormod = rsurface.colormod;
2086         float m16f[16];
2087         matrix4x4_t tempmatrix;
2088         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2089         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2090                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2091         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2092                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2093         if (rsurfacepass == RSURFPASS_BACKGROUND)
2094         {
2095                 // distorted background
2096                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2097                 {
2098                         mode = SHADERMODE_WATER;
2099                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2100                         {
2101                                 // this is the right thing to do for wateralpha
2102                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2103                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2104                         }
2105                         else
2106                         {
2107                                 // this is the right thing to do for entity alpha
2108                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2109                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110                         }
2111                 }
2112                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2113                 {
2114                         mode = SHADERMODE_REFRACTION;
2115                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2117                 }
2118                 else
2119                 {
2120                         mode = SHADERMODE_GENERIC;
2121                         permutation |= SHADERPERMUTATION_DIFFUSE;
2122                         GL_BlendFunc(GL_ONE, GL_ZERO);
2123                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2124                 }
2125         }
2126         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2127         {
2128                 if (r_glsl_offsetmapping.integer)
2129                 {
2130                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2131                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2132                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2133                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2134                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2135                         {
2136                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2137                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2138                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2139                         }
2140                 }
2141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143                 // normalmap (deferred prepass), may use alpha test on diffuse
2144                 mode = SHADERMODE_DEFERREDGEOMETRY;
2145                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2146                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2147                 GL_BlendFunc(GL_ONE, GL_ZERO);
2148                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149         }
2150         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2151         {
2152                 if (r_glsl_offsetmapping.integer)
2153                 {
2154                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2155                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2156                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2157                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2158                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2159                         {
2160                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2161                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2162                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2163                         }
2164                 }
2165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2167                 // light source
2168                 mode = SHADERMODE_LIGHTSOURCE;
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2173                 if (diffusescale > 0)
2174                         permutation |= SHADERPERMUTATION_DIFFUSE;
2175                 if (specularscale > 0)
2176                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177                 if (r_refdef.fogenabled)
2178                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179                 if (rsurface.texture->colormapping)
2180                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2181                 if (r_shadow_usingshadowmap2d)
2182                 {
2183                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184                         if(r_shadow_shadowmapvsdct)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2186
2187                         if (r_shadow_shadowmapsampler)
2188                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189                         if (r_shadow_shadowmappcf > 1)
2190                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191                         else if (r_shadow_shadowmappcf)
2192                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2193                 }
2194                 if (rsurface.texture->reflectmasktexture)
2195                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2198         }
2199         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2200         {
2201                 if (r_glsl_offsetmapping.integer)
2202                 {
2203                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2204                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2205                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2206                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2207                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2208                         {
2209                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2210                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2211                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2212                         }
2213                 }
2214                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2215                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2216                 // unshaded geometry (fullbright or ambient model lighting)
2217                 mode = SHADERMODE_FLATCOLOR;
2218                 ambientscale = diffusescale = specularscale = 0;
2219                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2220                         permutation |= SHADERPERMUTATION_GLOW;
2221                 if (r_refdef.fogenabled)
2222                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2223                 if (rsurface.texture->colormapping)
2224                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2225                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2226                 {
2227                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2228                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2229
2230                         if (r_shadow_shadowmapsampler)
2231                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2232                         if (r_shadow_shadowmappcf > 1)
2233                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2234                         else if (r_shadow_shadowmappcf)
2235                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2238                         permutation |= SHADERPERMUTATION_REFLECTION;
2239                 if (rsurface.texture->reflectmasktexture)
2240                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2241                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2242                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2243         }
2244         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2245         {
2246                 if (r_glsl_offsetmapping.integer)
2247                 {
2248                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2249                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2250                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2251                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2252                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2253                         {
2254                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2255                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2256                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2257                         }
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261                 // directional model lighting
2262                 mode = SHADERMODE_LIGHTDIRECTION;
2263                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2264                         permutation |= SHADERPERMUTATION_GLOW;
2265                 permutation |= SHADERPERMUTATION_DIFFUSE;
2266                 if (specularscale > 0)
2267                         permutation |= SHADERPERMUTATION_SPECULAR;
2268                 if (r_refdef.fogenabled)
2269                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270                 if (rsurface.texture->colormapping)
2271                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2272                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273                 {
2274                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276
2277                         if (r_shadow_shadowmapsampler)
2278                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279                         if (r_shadow_shadowmappcf > 1)
2280                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281                         else if (r_shadow_shadowmappcf)
2282                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2283                 }
2284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285                         permutation |= SHADERPERMUTATION_REFLECTION;
2286                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2287                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2288                 if (rsurface.texture->reflectmasktexture)
2289                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2290                 if (r_shadow_bouncegridtexture)
2291                 {
2292                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2293                         if (r_shadow_bouncegriddirectional)
2294                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2295                 }
2296                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2298         }
2299         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2300         {
2301                 if (r_glsl_offsetmapping.integer)
2302                 {
2303                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2304                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2305                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2306                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2307                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2308                         {
2309                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2310                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2311                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2312                         }
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316                 // ambient model lighting
2317                 mode = SHADERMODE_LIGHTDIRECTION;
2318                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319                         permutation |= SHADERPERMUTATION_GLOW;
2320                 if (r_refdef.fogenabled)
2321                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2322                 if (rsurface.texture->colormapping)
2323                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2324                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2325                 {
2326                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328
2329                         if (r_shadow_shadowmapsampler)
2330                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2331                         if (r_shadow_shadowmappcf > 1)
2332                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2333                         else if (r_shadow_shadowmappcf)
2334                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2335                 }
2336                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2337                         permutation |= SHADERPERMUTATION_REFLECTION;
2338                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2339                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2340                 if (rsurface.texture->reflectmasktexture)
2341                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2342                 if (r_shadow_bouncegridtexture)
2343                 {
2344                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2345                         if (r_shadow_bouncegriddirectional)
2346                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2347                 }
2348                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2350         }
2351         else
2352         {
2353                 if (r_glsl_offsetmapping.integer)
2354                 {
2355                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2356                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2357                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2358                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2359                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2360                         {
2361                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2362                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2363                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2364                         }
2365                 }
2366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2368                 // lightmapped wall
2369                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2370                         permutation |= SHADERPERMUTATION_GLOW;
2371                 if (r_refdef.fogenabled)
2372                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2373                 if (rsurface.texture->colormapping)
2374                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2375                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2376                 {
2377                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2378                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2379
2380                         if (r_shadow_shadowmapsampler)
2381                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2382                         if (r_shadow_shadowmappcf > 1)
2383                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2384                         else if (r_shadow_shadowmappcf)
2385                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2386                 }
2387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2388                         permutation |= SHADERPERMUTATION_REFLECTION;
2389                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2390                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2391                 if (rsurface.texture->reflectmasktexture)
2392                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2393                 if (FAKELIGHT_ENABLED)
2394                 {
2395                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2396                         mode = SHADERMODE_FAKELIGHT;
2397                         permutation |= SHADERPERMUTATION_DIFFUSE;
2398                         if (specularscale > 0)
2399                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2400                 }
2401                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2402                 {
2403                         // deluxemapping (light direction texture)
2404                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2405                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2406                         else
2407                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2408                         permutation |= SHADERPERMUTATION_DIFFUSE;
2409                         if (specularscale > 0)
2410                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2411                 }
2412                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2413                 {
2414                         // fake deluxemapping (uniform light direction in tangentspace)
2415                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2416                         permutation |= SHADERPERMUTATION_DIFFUSE;
2417                         if (specularscale > 0)
2418                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2419                 }
2420                 else if (rsurface.uselightmaptexture)
2421                 {
2422                         // ordinary lightmapping (q1bsp, q3bsp)
2423                         mode = SHADERMODE_LIGHTMAP;
2424                 }
2425                 else
2426                 {
2427                         // ordinary vertex coloring (q3bsp)
2428                         mode = SHADERMODE_VERTEXCOLOR;
2429                 }
2430                 if (r_shadow_bouncegridtexture)
2431                 {
2432                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2433                         if (r_shadow_bouncegriddirectional)
2434                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2435                 }
2436                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2437                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2438         }
2439         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2440                 colormod = dummy_colormod;
2441         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2442                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2443         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2444                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2445         switch(vid.renderpath)
2446         {
2447         case RENDERPATH_D3D9:
2448 #ifdef SUPPORTD3D
2449                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2450                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2451                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2452                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2453                 if (mode == SHADERMODE_LIGHTSOURCE)
2454                 {
2455                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2456                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457                 }
2458                 else
2459                 {
2460                         if (mode == SHADERMODE_LIGHTDIRECTION)
2461                         {
2462                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2463                         }
2464                 }
2465                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2466                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2467                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2468                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2469                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2470
2471                 if (mode == SHADERMODE_LIGHTSOURCE)
2472                 {
2473                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2474                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2475                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2476                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2477                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2478
2479                         // additive passes are only darkened by fog, not tinted
2480                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2481                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2482                 }
2483                 else
2484                 {
2485                         if (mode == SHADERMODE_FLATCOLOR)
2486                         {
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2488                         }
2489                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2490                         {
2491                                 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]);
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2493                                 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);
2494                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2496                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2497                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2498                         }
2499                         else
2500                         {
2501                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2502                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2503                                 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);
2504                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2506                         }
2507                         // additive passes are only darkened by fog, not tinted
2508                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2509                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2510                         else
2511                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2512                         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);
2513                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2514                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2515                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2516                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2517                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2518                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2519                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2520                         if (mode == SHADERMODE_WATER)
2521                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2522                 }
2523                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2524                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2525                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2526                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2527                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 if (rsurface.texture->pantstexture)
2529                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2530                 else
2531                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2532                 if (rsurface.texture->shirttexture)
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2534                 else
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2536                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2538                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2539                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2540                 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2541                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2542                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2543
2544                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2545                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2546                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2547                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2548                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2549                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2550                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2551                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2552                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2553                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2554                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2555                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2556                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2557                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2558                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2559                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2560                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2561                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2562                 {
2563                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2564                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2565                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2566                 }
2567                 else
2568                 {
2569                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2570                 }
2571 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2572 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2573                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2574                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2575                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2576                 {
2577                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2578                         if (rsurface.rtlight)
2579                         {
2580                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2581                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2582                         }
2583                 }
2584 #endif
2585                 break;
2586         case RENDERPATH_D3D10:
2587                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2588                 break;
2589         case RENDERPATH_D3D11:
2590                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2591                 break;
2592         case RENDERPATH_GL20:
2593         case RENDERPATH_GLES2:
2594                 if (!vid.useinterleavedarrays)
2595                 {
2596                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2597                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2598                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2599                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2600                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2601                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2602                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2603                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2604                 }
2605                 else
2606                 {
2607                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2608                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2609                 }
2610                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2611                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2612                 if (mode == SHADERMODE_LIGHTSOURCE)
2613                 {
2614                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2615                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2616                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2617                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2618                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2619                         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);
2620         
2621                         // additive passes are only darkened by fog, not tinted
2622                         if (r_glsl_permutation->loc_FogColor >= 0)
2623                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2624                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                 }
2626                 else
2627                 {
2628                         if (mode == SHADERMODE_FLATCOLOR)
2629                         {
2630                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2631                         }
2632                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2633                         {
2634                                 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]);
2635                                 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]);
2636                                 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);
2637                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2638                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2639                                 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]);
2640                                 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]);
2641                         }
2642                         else
2643                         {
2644                                 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]);
2645                                 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]);
2646                                 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);
2647                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2648                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2649                         }
2650                         // additive passes are only darkened by fog, not tinted
2651                         if (r_glsl_permutation->loc_FogColor >= 0)
2652                         {
2653                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2654                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2655                                 else
2656                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2657                         }
2658                         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);
2659                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2660                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2661                         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]);
2662                         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]);
2663                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2664                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2665                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2666                         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]);
2667                 }
2668                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2669                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2670                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2671                 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]);
2672                 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]);
2673
2674                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2675                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2676                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2677                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2678                 {
2679                         if (rsurface.texture->pantstexture)
2680                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2681                         else
2682                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2683                 }
2684                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2685                 {
2686                         if (rsurface.texture->shirttexture)
2687                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2688                         else
2689                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2690                 }
2691                 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]);
2692                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2693                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2694                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2695                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2696                 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]);
2697                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2699                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2700
2701                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2702                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2703                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2704                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2705                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2706                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2708                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2709                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2710                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2711                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2712                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2713                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2714                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2715                 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);
2716                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2717                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2718                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2721                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2722                 {
2723                         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);
2724                         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);
2725                         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);
2726                 }
2727                 else
2728                 {
2729                         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);
2730                 }
2731                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2732                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2733                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2734                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2735                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736                 {
2737                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2738                         if (rsurface.rtlight)
2739                         {
2740                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2741                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2742                         }
2743                 }
2744                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2745                 CHECKGLERROR
2746                 break;
2747         case RENDERPATH_GL13:
2748         case RENDERPATH_GL11:
2749                 break;
2750         case RENDERPATH_SOFT:
2751                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2752                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2753                 R_SetupShader_SetPermutationSoft(mode, permutation);
2754                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2755                 if (mode == SHADERMODE_LIGHTSOURCE)
2756                 {
2757                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2758                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2761                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2762                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2763         
2764                         // additive passes are only darkened by fog, not tinted
2765                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2766                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2767                 }
2768                 else
2769                 {
2770                         if (mode == SHADERMODE_FLATCOLOR)
2771                         {
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2773                         }
2774                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2775                         {
2776                                 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]);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2778                                 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);
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2781                                 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]);
2782                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2783                         }
2784                         else
2785                         {
2786                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2788                                 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);
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2791                         }
2792                         // additive passes are only darkened by fog, not tinted
2793                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2794                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2795                         else
2796                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2797                         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);
2798                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2799                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2800                         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]);
2801                         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]);
2802                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2803                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2804                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2805                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2806                 }
2807                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2808                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2809                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2810                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2811                 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]);
2812
2813                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2814                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2815                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2816                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2817                 {
2818                         if (rsurface.texture->pantstexture)
2819                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2820                         else
2821                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2822                 }
2823                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2824                 {
2825                         if (rsurface.texture->shirttexture)
2826                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2827                         else
2828                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2829                 }
2830                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2831                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2832                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2833                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2834                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2835                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2836                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2837
2838                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2839                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2840                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2841                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2843                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2844                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2845                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2846                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2847                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2848                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2849                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2850                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2851                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2852                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2853                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2854                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2855                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2856                 {
2857                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2858                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2859                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2860                 }
2861                 else
2862                 {
2863                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864                 }
2865 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2866 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2867                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2868                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2869                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2870                 {
2871                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2872                         if (rsurface.rtlight)
2873                         {
2874                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2875                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2876                         }
2877                 }
2878                 break;
2879         }
2880 }
2881
2882 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2883 {
2884         // select a permutation of the lighting shader appropriate to this
2885         // combination of texture, entity, light source, and fogging, only use the
2886         // minimum features necessary to avoid wasting rendering time in the
2887         // fragment shader on features that are not being used
2888         unsigned int permutation = 0;
2889         unsigned int mode = 0;
2890         const float *lightcolorbase = rtlight->currentcolor;
2891         float ambientscale = rtlight->ambientscale;
2892         float diffusescale = rtlight->diffusescale;
2893         float specularscale = rtlight->specularscale;
2894         // this is the location of the light in view space
2895         vec3_t viewlightorigin;
2896         // this transforms from view space (camera) to light space (cubemap)
2897         matrix4x4_t viewtolight;
2898         matrix4x4_t lighttoview;
2899         float viewtolight16f[16];
2900         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2901         // light source
2902         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2903         if (rtlight->currentcubemap != r_texture_whitecube)
2904                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2905         if (diffusescale > 0)
2906                 permutation |= SHADERPERMUTATION_DIFFUSE;
2907         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2908                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909         if (r_shadow_usingshadowmap2d)
2910         {
2911                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2912                 if (r_shadow_shadowmapvsdct)
2913                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2914
2915                 if (r_shadow_shadowmapsampler)
2916                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2917                 if (r_shadow_shadowmappcf > 1)
2918                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2919                 else if (r_shadow_shadowmappcf)
2920                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2921         }
2922         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2923         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2924         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2925         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2926         switch(vid.renderpath)
2927         {
2928         case RENDERPATH_D3D9:
2929 #ifdef SUPPORTD3D
2930                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2931                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2932                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2934                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2935                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2936                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2938                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2939                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2940                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2941
2942                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2943                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2944                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2945                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2946                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2947                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2948 #endif
2949                 break;
2950         case RENDERPATH_D3D10:
2951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952                 break;
2953         case RENDERPATH_D3D11:
2954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2955                 break;
2956         case RENDERPATH_GL20:
2957         case RENDERPATH_GLES2:
2958                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2961                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2962                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2963                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2964                 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]);
2965                 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]);
2966                 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));
2967                 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]);
2968                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2971                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2972                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2973                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2974                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2975                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2976                 break;
2977         case RENDERPATH_GL13:
2978         case RENDERPATH_GL11:
2979                 break;
2980         case RENDERPATH_SOFT:
2981                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2984                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2986                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988                 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]);
2989                 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));
2990                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2992
2993                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2994                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2995                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2996                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2997                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2998                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2999                 break;
3000         }
3001 }
3002
3003 #define SKINFRAME_HASH 1024
3004
3005 typedef struct
3006 {
3007         int loadsequence; // incremented each level change
3008         memexpandablearray_t array;
3009         skinframe_t *hash[SKINFRAME_HASH];
3010 }
3011 r_skinframe_t;
3012 r_skinframe_t r_skinframe;
3013
3014 void R_SkinFrame_PrepareForPurge(void)
3015 {
3016         r_skinframe.loadsequence++;
3017         // wrap it without hitting zero
3018         if (r_skinframe.loadsequence >= 200)
3019                 r_skinframe.loadsequence = 1;
3020 }
3021
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3023 {
3024         if (!skinframe)
3025                 return;
3026         // mark the skinframe as used for the purging code
3027         skinframe->loadsequence = r_skinframe.loadsequence;
3028 }
3029
3030 void R_SkinFrame_Purge(void)
3031 {
3032         int i;
3033         skinframe_t *s;
3034         for (i = 0;i < SKINFRAME_HASH;i++)
3035         {
3036                 for (s = r_skinframe.hash[i];s;s = s->next)
3037                 {
3038                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3039                         {
3040                                 if (s->merged == s->base)
3041                                         s->merged = NULL;
3042                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3044                                 R_PurgeTexture(s->merged);s->merged = NULL;
3045                                 R_PurgeTexture(s->base  );s->base   = NULL;
3046                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3047                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3048                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3049                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3050                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3051                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3052                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053                                 s->loadsequence = 0;
3054                         }
3055                 }
3056         }
3057 }
3058
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3060         skinframe_t *item;
3061         char basename[MAX_QPATH];
3062
3063         Image_StripImageExtension(name, basename, sizeof(basename));
3064
3065         if( last == NULL ) {
3066                 int hashindex;
3067                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068                 item = r_skinframe.hash[hashindex];
3069         } else {
3070                 item = last->next;
3071         }
3072
3073         // linearly search through the hash bucket
3074         for( ; item ; item = item->next ) {
3075                 if( !strcmp( item->basename, basename ) ) {
3076                         return item;
3077                 }
3078         }
3079         return NULL;
3080 }
3081
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3083 {
3084         skinframe_t *item;
3085         int hashindex;
3086         char basename[MAX_QPATH];
3087
3088         Image_StripImageExtension(name, basename, sizeof(basename));
3089
3090         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3093                         break;
3094
3095         if (!item) {
3096                 rtexture_t *dyntexture;
3097                 // check whether its a dynamic texture
3098                 dyntexture = CL_GetDynTexture( basename );
3099                 if (!add && !dyntexture)
3100                         return NULL;
3101                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102                 memset(item, 0, sizeof(*item));
3103                 strlcpy(item->basename, basename, sizeof(item->basename));
3104                 item->base = dyntexture; // either NULL or dyntexture handle
3105                 item->textureflags = textureflags;
3106                 item->comparewidth = comparewidth;
3107                 item->compareheight = compareheight;
3108                 item->comparecrc = comparecrc;
3109                 item->next = r_skinframe.hash[hashindex];
3110                 r_skinframe.hash[hashindex] = item;
3111         }
3112         else if( item->base == NULL )
3113         {
3114                 rtexture_t *dyntexture;
3115                 // check whether its a dynamic texture
3116                 // 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]
3117                 dyntexture = CL_GetDynTexture( basename );
3118                 item->base = dyntexture; // either NULL or dyntexture handle
3119         }
3120
3121         R_SkinFrame_MarkUsed(item);
3122         return item;
3123 }
3124
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3126         { \
3127                 unsigned long long avgcolor[5], wsum; \
3128                 int pix, comp, w; \
3129                 avgcolor[0] = 0; \
3130                 avgcolor[1] = 0; \
3131                 avgcolor[2] = 0; \
3132                 avgcolor[3] = 0; \
3133                 avgcolor[4] = 0; \
3134                 wsum = 0; \
3135                 for(pix = 0; pix < cnt; ++pix) \
3136                 { \
3137                         w = 0; \
3138                         for(comp = 0; comp < 3; ++comp) \
3139                                 w += getpixel; \
3140                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3141                         { \
3142                                 ++wsum; \
3143                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                                 w = getpixel; \
3145                                 for(comp = 0; comp < 3; ++comp) \
3146                                         avgcolor[comp] += getpixel * w; \
3147                                 avgcolor[3] += w; \
3148                         } \
3149                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150                         avgcolor[4] += getpixel; \
3151                 } \
3152                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3153                         avgcolor[3] = 1; \
3154                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3158         }
3159
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3162 {
3163         int j;
3164         unsigned char *pixels;
3165         unsigned char *bumppixels;
3166         unsigned char *basepixels = NULL;
3167         int basepixels_width = 0;
3168         int basepixels_height = 0;
3169         skinframe_t *skinframe;
3170         rtexture_t *ddsbase = NULL;
3171         qboolean ddshasalpha = false;
3172         float ddsavgcolor[4];
3173         char basename[MAX_QPATH];
3174         int miplevel = R_PicmipForFlags(textureflags);
3175         int savemiplevel = miplevel;
3176         int mymiplevel;
3177
3178         if (cls.state == ca_dedicated)
3179                 return NULL;
3180
3181         // return an existing skinframe if already loaded
3182         // if loading of the first image fails, don't make a new skinframe as it
3183         // would cause all future lookups of this to be missing
3184         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185         if (skinframe && skinframe->base)
3186                 return skinframe;
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         // check for DDS texture file first
3191         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3192         {
3193                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3194                 if (basepixels == NULL)
3195                         return NULL;
3196         }
3197
3198         // FIXME handle miplevel
3199
3200         if (developer_loading.integer)
3201                 Con_Printf("loading skin \"%s\"\n", name);
3202
3203         // we've got some pixels to store, so really allocate this new texture now
3204         if (!skinframe)
3205                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206         skinframe->stain = NULL;
3207         skinframe->merged = NULL;
3208         skinframe->base = NULL;
3209         skinframe->pants = NULL;
3210         skinframe->shirt = NULL;
3211         skinframe->nmap = NULL;
3212         skinframe->gloss = NULL;
3213         skinframe->glow = NULL;
3214         skinframe->fog = NULL;
3215         skinframe->reflect = NULL;
3216         skinframe->hasalpha = false;
3217
3218         if (ddsbase)
3219         {
3220                 skinframe->base = ddsbase;
3221                 skinframe->hasalpha = ddshasalpha;
3222                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223                 if (r_loadfog && skinframe->hasalpha)
3224                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225                 //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]);
3226         }
3227         else
3228         {
3229                 basepixels_width = image_width;
3230                 basepixels_height = image_height;
3231                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3232                 if (textureflags & TEXF_ALPHA)
3233                 {
3234                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3235                         {
3236                                 if (basepixels[j] < 255)
3237                                 {
3238                                         skinframe->hasalpha = true;
3239                                         break;
3240                                 }
3241                         }
3242                         if (r_loadfog && skinframe->hasalpha)
3243                         {
3244                                 // has transparent pixels
3245                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3247                                 {
3248                                         pixels[j+0] = 255;
3249                                         pixels[j+1] = 255;
3250                                         pixels[j+2] = 255;
3251                                         pixels[j+3] = basepixels[j+3];
3252                                 }
3253                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3254                                 Mem_Free(pixels);
3255                         }
3256                 }
3257                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258                 //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]);
3259                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3261                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3263         }
3264
3265         if (r_loaddds)
3266         {
3267                 mymiplevel = savemiplevel;
3268                 if (r_loadnormalmap)
3269                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3270                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271                 if (r_loadgloss)
3272                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276         }
3277
3278         // _norm is the name used by tenebrae and has been adopted as standard
3279         if (r_loadnormalmap && skinframe->nmap == NULL)
3280         {
3281                 mymiplevel = savemiplevel;
3282                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3285                         Mem_Free(pixels);
3286                         pixels = NULL;
3287                 }
3288                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289                 {
3290                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3293                         Mem_Free(pixels);
3294                         Mem_Free(bumppixels);
3295                 }
3296                 else if (r_shadow_bumpscale_basetexture.value > 0)
3297                 {
3298                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3301                         Mem_Free(pixels);
3302                 }
3303                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3305         }
3306
3307         // _luma is supported only for tenebrae compatibility
3308         // _glow is the preferred name
3309         mymiplevel = savemiplevel;
3310         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3311         {
3312                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3313                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3315                 Mem_Free(pixels);pixels = NULL;
3316         }
3317
3318         mymiplevel = savemiplevel;
3319         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3320         {
3321                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3324                 Mem_Free(pixels);
3325                 pixels = NULL;
3326         }
3327
3328         mymiplevel = savemiplevel;
3329         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3330         {
3331                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3334                 Mem_Free(pixels);
3335                 pixels = NULL;
3336         }
3337
3338         mymiplevel = savemiplevel;
3339         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3340         {
3341                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3344                 Mem_Free(pixels);
3345                 pixels = NULL;
3346         }
3347
3348         mymiplevel = savemiplevel;
3349         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3350         {
3351                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3352                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3354                 Mem_Free(pixels);
3355                 pixels = NULL;
3356         }
3357
3358         if (basepixels)
3359                 Mem_Free(basepixels);
3360
3361         return skinframe;
3362 }
3363
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3366 {
3367         int i;
3368         unsigned char *temp1, *temp2;
3369         skinframe_t *skinframe;
3370
3371         if (cls.state == ca_dedicated)
3372                 return NULL;
3373
3374         // if already loaded just return it, otherwise make a new skinframe
3375         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376         if (skinframe && skinframe->base)
3377                 return skinframe;
3378
3379         skinframe->stain = NULL;
3380         skinframe->merged = NULL;
3381         skinframe->base = NULL;
3382         skinframe->pants = NULL;
3383         skinframe->shirt = NULL;
3384         skinframe->nmap = NULL;
3385         skinframe->gloss = NULL;
3386         skinframe->glow = NULL;
3387         skinframe->fog = NULL;
3388         skinframe->reflect = NULL;
3389         skinframe->hasalpha = false;
3390
3391         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3392         if (!skindata)
3393                 return NULL;
3394
3395         if (developer_loading.integer)
3396                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3397
3398         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3399         {
3400                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401                 temp2 = temp1 + width * height * 4;
3402                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3404                 Mem_Free(temp1);
3405         }
3406         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3407         if (textureflags & TEXF_ALPHA)
3408         {
3409                 for (i = 3;i < width * height * 4;i += 4)
3410                 {
3411                         if (skindata[i] < 255)
3412                         {
3413                                 skinframe->hasalpha = true;
3414                                 break;
3415                         }
3416                 }
3417                 if (r_loadfog && skinframe->hasalpha)
3418                 {
3419                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420                         memcpy(fogpixels, skindata, width * height * 4);
3421                         for (i = 0;i < width * height * 4;i += 4)
3422                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424                         Mem_Free(fogpixels);
3425                 }
3426         }
3427
3428         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429         //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]);
3430
3431         return skinframe;
3432 }
3433
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3435 {
3436         int i;
3437         int featuresmask;
3438         skinframe_t *skinframe;
3439
3440         if (cls.state == ca_dedicated)
3441                 return NULL;
3442
3443         // if already loaded just return it, otherwise make a new skinframe
3444         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445         if (skinframe && skinframe->base)
3446                 return skinframe;
3447
3448         skinframe->stain = NULL;
3449         skinframe->merged = NULL;
3450         skinframe->base = NULL;
3451         skinframe->pants = NULL;
3452         skinframe->shirt = NULL;
3453         skinframe->nmap = NULL;
3454         skinframe->gloss = NULL;
3455         skinframe->glow = NULL;
3456         skinframe->fog = NULL;
3457         skinframe->reflect = NULL;
3458         skinframe->hasalpha = false;
3459
3460         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3461         if (!skindata)
3462                 return NULL;
3463
3464         if (developer_loading.integer)
3465                 Con_Printf("loading quake skin \"%s\"\n", name);
3466
3467         // 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)
3468         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469         memcpy(skinframe->qpixels, skindata, width*height);
3470         skinframe->qwidth = width;
3471         skinframe->qheight = height;
3472
3473         featuresmask = 0;
3474         for (i = 0;i < width * height;i++)
3475                 featuresmask |= palette_featureflags[skindata[i]];
3476
3477         skinframe->hasalpha = false;
3478         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480         skinframe->qgeneratemerged = true;
3481         skinframe->qgeneratebase = skinframe->qhascolormapping;
3482         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3483
3484         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485         //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]);
3486
3487         return skinframe;
3488 }
3489
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3491 {
3492         int width;
3493         int height;
3494         unsigned char *skindata;
3495
3496         if (!skinframe->qpixels)
3497                 return;
3498
3499         if (!skinframe->qhascolormapping)
3500                 colormapped = false;
3501
3502         if (colormapped)
3503         {
3504                 if (!skinframe->qgeneratebase)
3505                         return;
3506         }
3507         else
3508         {
3509                 if (!skinframe->qgeneratemerged)
3510                         return;
3511         }
3512
3513         width = skinframe->qwidth;
3514         height = skinframe->qheight;
3515         skindata = skinframe->qpixels;
3516
3517         if (skinframe->qgeneratenmap)
3518         {
3519                 unsigned char *temp1, *temp2;
3520                 skinframe->qgeneratenmap = false;
3521                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522                 temp2 = temp1 + width * height * 4;
3523                 // use either a custom palette or the quake palette
3524                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3527                 Mem_Free(temp1);
3528         }
3529
3530         if (skinframe->qgenerateglow)
3531         {
3532                 skinframe->qgenerateglow = false;
3533                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3534         }
3535
3536         if (colormapped)
3537         {
3538                 skinframe->qgeneratebase = false;
3539                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3540                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3541                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3542         }
3543         else
3544         {
3545                 skinframe->qgeneratemerged = false;
3546                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3547         }
3548
3549         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3550         {
3551                 Mem_Free(skinframe->qpixels);
3552                 skinframe->qpixels = NULL;
3553         }
3554 }
3555
3556 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)
3557 {
3558         int i;
3559         skinframe_t *skinframe;
3560
3561         if (cls.state == ca_dedicated)
3562                 return NULL;
3563
3564         // if already loaded just return it, otherwise make a new skinframe
3565         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566         if (skinframe && skinframe->base)
3567                 return skinframe;
3568
3569         skinframe->stain = NULL;
3570         skinframe->merged = NULL;
3571         skinframe->base = NULL;
3572         skinframe->pants = NULL;
3573         skinframe->shirt = NULL;
3574         skinframe->nmap = NULL;
3575         skinframe->gloss = NULL;
3576         skinframe->glow = NULL;
3577         skinframe->fog = NULL;
3578         skinframe->reflect = NULL;
3579         skinframe->hasalpha = false;
3580
3581         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3582         if (!skindata)
3583                 return NULL;
3584
3585         if (developer_loading.integer)
3586                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3587
3588         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589         if (textureflags & TEXF_ALPHA)
3590         {
3591                 for (i = 0;i < width * height;i++)
3592                 {
3593                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3594                         {
3595                                 skinframe->hasalpha = true;
3596                                 break;
3597                         }
3598                 }
3599                 if (r_loadfog && skinframe->hasalpha)
3600                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3601         }
3602
3603         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604         //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]);
3605
3606         return skinframe;
3607 }
3608
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3610 {
3611         skinframe_t *skinframe;
3612
3613         if (cls.state == ca_dedicated)
3614                 return NULL;
3615
3616         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617         skinframe->stain = NULL;
3618         skinframe->merged = NULL;
3619         skinframe->base = NULL;
3620         skinframe->pants = NULL;
3621         skinframe->shirt = NULL;
3622         skinframe->nmap = NULL;
3623         skinframe->gloss = NULL;
3624         skinframe->glow = NULL;
3625         skinframe->fog = NULL;
3626         skinframe->reflect = NULL;
3627         skinframe->hasalpha = false;
3628
3629         skinframe->avgcolor[0] = rand() / RAND_MAX;
3630         skinframe->avgcolor[1] = rand() / RAND_MAX;
3631         skinframe->avgcolor[2] = rand() / RAND_MAX;
3632         skinframe->avgcolor[3] = 1;
3633
3634         return skinframe;
3635 }
3636
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3639 {
3640         const char *suffix;
3641         qboolean flipx, flipy, flipdiagonal;
3642 }
3643 suffixinfo_t;
3644 static suffixinfo_t suffix[3][6] =
3645 {
3646         {
3647                 {"px",   false, false, false},
3648                 {"nx",   false, false, false},
3649                 {"py",   false, false, false},
3650                 {"ny",   false, false, false},
3651                 {"pz",   false, false, false},
3652                 {"nz",   false, false, false}
3653         },
3654         {
3655                 {"posx", false, false, false},
3656                 {"negx", false, false, false},
3657                 {"posy", false, false, false},
3658                 {"negy", false, false, false},
3659                 {"posz", false, false, false},
3660                 {"negz", false, false, false}
3661         },
3662         {
3663                 {"rt",    true, false,  true},
3664                 {"lf",   false,  true,  true},
3665                 {"ft",    true,  true, false},
3666                 {"bk",   false, false, false},
3667                 {"up",    true, false,  true},
3668                 {"dn",    true, false,  true}
3669         }
3670 };
3671
3672 static int componentorder[4] = {0, 1, 2, 3};
3673
3674 rtexture_t *R_LoadCubemap(const char *basename)
3675 {
3676         int i, j, cubemapsize;
3677         unsigned char *cubemappixels, *image_buffer;
3678         rtexture_t *cubemaptexture;
3679         char name[256];
3680         // must start 0 so the first loadimagepixels has no requested width/height
3681         cubemapsize = 0;
3682         cubemappixels = NULL;
3683         cubemaptexture = NULL;
3684         // keep trying different suffix groups (posx, px, rt) until one loads
3685         for (j = 0;j < 3 && !cubemappixels;j++)
3686         {
3687                 // load the 6 images in the suffix group
3688                 for (i = 0;i < 6;i++)
3689                 {
3690                         // generate an image name based on the base and and suffix
3691                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3692                         // load it
3693                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3694                         {
3695                                 // an image loaded, make sure width and height are equal
3696                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3697                                 {
3698                                         // if this is the first image to load successfully, allocate the cubemap memory
3699                                         if (!cubemappixels && image_width >= 1)
3700                                         {
3701                                                 cubemapsize = image_width;
3702                                                 // note this clears to black, so unavailable sides are black
3703                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3704                                         }
3705                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3706                                         if (cubemappixels)
3707                                                 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);
3708                                 }
3709                                 else
3710                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3711                                 // free the image
3712                                 Mem_Free(image_buffer);
3713                         }
3714                 }
3715         }
3716         // if a cubemap loaded, upload it
3717         if (cubemappixels)
3718         {
3719                 if (developer_loading.integer)
3720                         Con_Printf("loading cubemap \"%s\"\n", basename);
3721
3722                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3723                 Mem_Free(cubemappixels);
3724         }
3725         else
3726         {
3727                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728                 if (developer_loading.integer)
3729                 {
3730                         Con_Printf("(tried tried images ");
3731                         for (j = 0;j < 3;j++)
3732                                 for (i = 0;i < 6;i++)
3733                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734                         Con_Print(" and was unable to find any of them).\n");
3735                 }
3736         }
3737         return cubemaptexture;
3738 }
3739
3740 rtexture_t *R_GetCubemap(const char *basename)
3741 {
3742         int i;
3743         for (i = 0;i < r_texture_numcubemaps;i++)
3744                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3745                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3746         if (i >= MAX_CUBEMAPS)
3747                 return r_texture_whitecube;
3748         r_texture_numcubemaps++;
3749         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3750         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3751         return r_texture_cubemaps[i].texture;
3752 }
3753
3754 void R_FreeCubemaps(void)
3755 {
3756         int i;
3757         for (i = 0;i < r_texture_numcubemaps;i++)
3758         {
3759                 if (developer_loading.integer)
3760                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3761                 if (r_texture_cubemaps[i].texture)
3762                         R_FreeTexture(r_texture_cubemaps[i].texture);
3763         }
3764         r_texture_numcubemaps = 0;
3765 }
3766
3767 void R_Main_FreeViewCache(void)
3768 {
3769         if (r_refdef.viewcache.entityvisible)
3770                 Mem_Free(r_refdef.viewcache.entityvisible);
3771         if (r_refdef.viewcache.world_pvsbits)
3772                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3773         if (r_refdef.viewcache.world_leafvisible)
3774                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3775         if (r_refdef.viewcache.world_surfacevisible)
3776                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3777         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3778 }
3779
3780 void R_Main_ResizeViewCache(void)
3781 {
3782         int numentities = r_refdef.scene.numentities;
3783         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3784         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3785         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3786         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3787         if (r_refdef.viewcache.maxentities < numentities)
3788         {
3789                 r_refdef.viewcache.maxentities = numentities;
3790                 if (r_refdef.viewcache.entityvisible)
3791                         Mem_Free(r_refdef.viewcache.entityvisible);
3792                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3793         }
3794         if (r_refdef.viewcache.world_numclusters != numclusters)
3795         {
3796                 r_refdef.viewcache.world_numclusters = numclusters;
3797                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3798                 if (r_refdef.viewcache.world_pvsbits)
3799                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3800                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3801         }
3802         if (r_refdef.viewcache.world_numleafs != numleafs)
3803         {
3804                 r_refdef.viewcache.world_numleafs = numleafs;
3805                 if (r_refdef.viewcache.world_leafvisible)
3806                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3807                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3808         }
3809         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3810         {
3811                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3812                 if (r_refdef.viewcache.world_surfacevisible)
3813                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3814                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3815         }
3816 }
3817
3818 extern rtexture_t *loadingscreentexture;
3819 void gl_main_start(void)
3820 {
3821         loadingscreentexture = NULL;
3822         r_texture_blanknormalmap = NULL;
3823         r_texture_white = NULL;
3824         r_texture_grey128 = NULL;
3825         r_texture_black = NULL;
3826         r_texture_whitecube = NULL;
3827         r_texture_normalizationcube = NULL;
3828         r_texture_fogattenuation = NULL;
3829         r_texture_fogheighttexture = NULL;
3830         r_texture_gammaramps = NULL;
3831         r_texture_numcubemaps = 0;
3832
3833         r_loaddds = r_texture_dds_load.integer != 0;
3834         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3835
3836         switch(vid.renderpath)
3837         {
3838         case RENDERPATH_GL20:
3839         case RENDERPATH_D3D9:
3840         case RENDERPATH_D3D10:
3841         case RENDERPATH_D3D11:
3842         case RENDERPATH_SOFT:
3843                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844                 Cvar_SetValueQuick(&gl_combine, 1);
3845                 Cvar_SetValueQuick(&r_glsl, 1);
3846                 r_loadnormalmap = true;
3847                 r_loadgloss = true;
3848                 r_loadfog = false;
3849                 break;
3850         case RENDERPATH_GL13:
3851                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852                 Cvar_SetValueQuick(&gl_combine, 1);
3853                 Cvar_SetValueQuick(&r_glsl, 0);
3854                 r_loadnormalmap = false;
3855                 r_loadgloss = false;
3856                 r_loadfog = true;
3857                 break;
3858         case RENDERPATH_GL11:
3859                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3860                 Cvar_SetValueQuick(&gl_combine, 0);
3861                 Cvar_SetValueQuick(&r_glsl, 0);
3862                 r_loadnormalmap = false;
3863                 r_loadgloss = false;
3864                 r_loadfog = true;
3865                 break;
3866         case RENDERPATH_GLES2:
3867                 Cvar_SetValueQuick(&r_textureunits, 1);
3868                 Cvar_SetValueQuick(&gl_combine, 1);
3869                 Cvar_SetValueQuick(&r_glsl, 1);
3870                 r_loadnormalmap = true;
3871                 r_loadgloss = false;
3872                 r_loadfog = false;
3873                 break;
3874         }
3875
3876         R_AnimCache_Free();
3877         R_FrameData_Reset();
3878
3879         r_numqueries = 0;
3880         r_maxqueries = 0;
3881         memset(r_queries, 0, sizeof(r_queries));
3882
3883         r_qwskincache = NULL;
3884         r_qwskincache_size = 0;
3885
3886         // due to caching of texture_t references, the collision cache must be reset
3887         Collision_Cache_Reset(true);
3888
3889         // set up r_skinframe loading system for textures
3890         memset(&r_skinframe, 0, sizeof(r_skinframe));
3891         r_skinframe.loadsequence = 1;
3892         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3893
3894         r_main_texturepool = R_AllocTexturePool();
3895         R_BuildBlankTextures();
3896         R_BuildNoTexture();
3897         if (vid.support.arb_texture_cube_map)
3898         {
3899                 R_BuildWhiteCube();
3900                 R_BuildNormalizationCube();
3901         }
3902         r_texture_fogattenuation = NULL;
3903         r_texture_fogheighttexture = NULL;
3904         r_texture_gammaramps = NULL;
3905         //r_texture_fogintensity = NULL;
3906         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3907         memset(&r_waterstate, 0, sizeof(r_waterstate));
3908         r_glsl_permutation = NULL;
3909         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3910         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3911         glslshaderstring = NULL;
3912 #ifdef SUPPORTD3D
3913         r_hlsl_permutation = NULL;
3914         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3915         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3916 #endif
3917         hlslshaderstring = NULL;
3918         memset(&r_svbsp, 0, sizeof (r_svbsp));
3919
3920         r_refdef.fogmasktable_density = 0;
3921 }
3922
3923 void gl_main_shutdown(void)
3924 {
3925         R_AnimCache_Free();
3926         R_FrameData_Reset();
3927
3928         R_Main_FreeViewCache();
3929
3930         switch(vid.renderpath)
3931         {
3932         case RENDERPATH_GL11:
3933         case RENDERPATH_GL13:
3934         case RENDERPATH_GL20:
3935         case RENDERPATH_GLES2:
3936                 if (r_maxqueries)
3937                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3938                 break;
3939         case RENDERPATH_D3D9:
3940                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3941                 break;
3942         case RENDERPATH_D3D10:
3943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3944                 break;
3945         case RENDERPATH_D3D11:
3946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3947                 break;
3948         case RENDERPATH_SOFT:
3949                 break;
3950         }
3951
3952         r_numqueries = 0;
3953         r_maxqueries = 0;
3954         memset(r_queries, 0, sizeof(r_queries));
3955
3956         r_qwskincache = NULL;
3957         r_qwskincache_size = 0;
3958
3959         // clear out the r_skinframe state
3960         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961         memset(&r_skinframe, 0, sizeof(r_skinframe));
3962
3963         if (r_svbsp.nodes)
3964                 Mem_Free(r_svbsp.nodes);
3965         memset(&r_svbsp, 0, sizeof (r_svbsp));
3966         R_FreeTexturePool(&r_main_texturepool);
3967         loadingscreentexture = NULL;
3968         r_texture_blanknormalmap = NULL;
3969         r_texture_white = NULL;
3970         r_texture_grey128 = NULL;
3971         r_texture_black = NULL;
3972         r_texture_whitecube = NULL;
3973         r_texture_normalizationcube = NULL;
3974         r_texture_fogattenuation = NULL;
3975         r_texture_fogheighttexture = NULL;
3976         r_texture_gammaramps = NULL;
3977         r_texture_numcubemaps = 0;
3978         //r_texture_fogintensity = NULL;
3979         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980         memset(&r_waterstate, 0, sizeof(r_waterstate));
3981         R_GLSL_Restart_f();
3982
3983         r_glsl_permutation = NULL;
3984         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986         glslshaderstring = NULL;
3987 #ifdef SUPPORTD3D
3988         r_hlsl_permutation = NULL;
3989         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3991 #endif
3992         hlslshaderstring = NULL;
3993 }
3994
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3997 {
3998         // FIXME: move this code to client
3999         char *entities, entname[MAX_QPATH];
4000         if (r_qwskincache)
4001                 Mem_Free(r_qwskincache);
4002         r_qwskincache = NULL;
4003         r_qwskincache_size = 0;
4004         if (cl.worldmodel)
4005         {
4006                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4008                 {
4009                         CL_ParseEntityLump(entities);
4010                         Mem_Free(entities);
4011                         return;
4012                 }
4013                 if (cl.worldmodel->brush.entities)
4014                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4015         }
4016         R_Main_FreeViewCache();
4017
4018         R_FrameData_Reset();
4019 }
4020
4021 void GL_Main_Init(void)
4022 {
4023         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4024
4025         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028         if (gamemode == GAME_NEHAHRA)
4029         {
4030                 Cvar_RegisterVariable (&gl_fogenable);
4031                 Cvar_RegisterVariable (&gl_fogdensity);
4032                 Cvar_RegisterVariable (&gl_fogred);
4033                 Cvar_RegisterVariable (&gl_foggreen);
4034                 Cvar_RegisterVariable (&gl_fogblue);
4035                 Cvar_RegisterVariable (&gl_fogstart);
4036                 Cvar_RegisterVariable (&gl_fogend);
4037                 Cvar_RegisterVariable (&gl_skyclip);
4038         }
4039         Cvar_RegisterVariable(&r_motionblur);
4040         Cvar_RegisterVariable(&r_motionblur_maxblur);
4041         Cvar_RegisterVariable(&r_motionblur_bmin);
4042         Cvar_RegisterVariable(&r_motionblur_vmin);
4043         Cvar_RegisterVariable(&r_motionblur_vmax);
4044         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045         Cvar_RegisterVariable(&r_motionblur_randomize);
4046         Cvar_RegisterVariable(&r_damageblur);
4047         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049         Cvar_RegisterVariable(&r_equalize_entities_by);
4050         Cvar_RegisterVariable(&r_equalize_entities_to);
4051         Cvar_RegisterVariable(&r_depthfirst);
4052         Cvar_RegisterVariable(&r_useinfinitefarclip);
4053         Cvar_RegisterVariable(&r_farclip_base);
4054         Cvar_RegisterVariable(&r_farclip_world);
4055         Cvar_RegisterVariable(&r_nearclip);
4056         Cvar_RegisterVariable(&r_showbboxes);
4057         Cvar_RegisterVariable(&r_showsurfaces);
4058         Cvar_RegisterVariable(&r_showtris);
4059         Cvar_RegisterVariable(&r_shownormals);
4060         Cvar_RegisterVariable(&r_showlighting);
4061         Cvar_RegisterVariable(&r_showshadowvolumes);
4062         Cvar_RegisterVariable(&r_showcollisionbrushes);
4063         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4064         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4065         Cvar_RegisterVariable(&r_showdisabledepthtest);
4066         Cvar_RegisterVariable(&r_drawportals);
4067         Cvar_RegisterVariable(&r_drawentities);
4068         Cvar_RegisterVariable(&r_draw2d);
4069         Cvar_RegisterVariable(&r_drawworld);
4070         Cvar_RegisterVariable(&r_cullentities_trace);
4071         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4072         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4073         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4074         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4075         Cvar_RegisterVariable(&r_drawviewmodel);
4076         Cvar_RegisterVariable(&r_drawexteriormodel);
4077         Cvar_RegisterVariable(&r_speeds);
4078         Cvar_RegisterVariable(&r_fullbrights);
4079         Cvar_RegisterVariable(&r_wateralpha);
4080         Cvar_RegisterVariable(&r_dynamic);
4081         Cvar_RegisterVariable(&r_fakelight);
4082         Cvar_RegisterVariable(&r_fakelight_intensity);
4083         Cvar_RegisterVariable(&r_fullbright);
4084         Cvar_RegisterVariable(&r_shadows);
4085         Cvar_RegisterVariable(&r_shadows_darken);
4086         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4087         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4088         Cvar_RegisterVariable(&r_shadows_throwdistance);
4089         Cvar_RegisterVariable(&r_shadows_throwdirection);
4090         Cvar_RegisterVariable(&r_shadows_focus);
4091         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4092         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4093         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4094         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4095         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4096         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4097         Cvar_RegisterVariable(&r_fog_exp2);
4098         Cvar_RegisterVariable(&r_fog_clear);
4099         Cvar_RegisterVariable(&r_drawfog);
4100         Cvar_RegisterVariable(&r_transparentdepthmasking);
4101         Cvar_RegisterVariable(&r_texture_dds_load);
4102         Cvar_RegisterVariable(&r_texture_dds_save);
4103         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4104         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4105         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4106         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4107         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4108         Cvar_RegisterVariable(&r_textureunits);
4109         Cvar_RegisterVariable(&gl_combine);
4110         Cvar_RegisterVariable(&r_viewfbo);
4111         Cvar_RegisterVariable(&r_viewscale);
4112         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4113         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4114         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4115         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4116         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4117         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4118         Cvar_RegisterVariable(&r_glsl);
4119         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4120         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4121         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4122         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4123         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4124         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4125         Cvar_RegisterVariable(&r_glsl_postprocess);
4126         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4127         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4128         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4129         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4130         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4131         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4132         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4133         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4134
4135         Cvar_RegisterVariable(&r_water);
4136         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4137         Cvar_RegisterVariable(&r_water_clippingplanebias);
4138         Cvar_RegisterVariable(&r_water_refractdistort);
4139         Cvar_RegisterVariable(&r_water_reflectdistort);
4140         Cvar_RegisterVariable(&r_water_scissormode);
4141         Cvar_RegisterVariable(&r_lerpsprites);
4142         Cvar_RegisterVariable(&r_lerpmodels);
4143         Cvar_RegisterVariable(&r_lerplightstyles);
4144         Cvar_RegisterVariable(&r_waterscroll);
4145         Cvar_RegisterVariable(&r_bloom);
4146         Cvar_RegisterVariable(&r_bloom_colorscale);
4147         Cvar_RegisterVariable(&r_bloom_brighten);
4148         Cvar_RegisterVariable(&r_bloom_blur);
4149         Cvar_RegisterVariable(&r_bloom_resolution);
4150         Cvar_RegisterVariable(&r_bloom_colorexponent);
4151         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4152         Cvar_RegisterVariable(&r_hdr);
4153         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4154         Cvar_RegisterVariable(&r_hdr_glowintensity);
4155         Cvar_RegisterVariable(&r_hdr_range);
4156         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4157         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4158         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4159         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4160         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4161         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4162         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4163         Cvar_RegisterVariable(&developer_texturelogging);
4164         Cvar_RegisterVariable(&gl_lightmaps);
4165         Cvar_RegisterVariable(&r_test);
4166         Cvar_RegisterVariable(&r_glsl_saturation);
4167         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4168         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4169         Cvar_RegisterVariable(&r_framedatasize);
4170         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4171                 Cvar_SetValue("r_fullbrights", 0);
4172         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4173
4174         Cvar_RegisterVariable(&r_track_sprites);
4175         Cvar_RegisterVariable(&r_track_sprites_flags);
4176         Cvar_RegisterVariable(&r_track_sprites_scalew);
4177         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4178         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4179         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4180         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4181         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4182 }
4183
4184 extern void R_Textures_Init(void);
4185 extern void GL_Draw_Init(void);
4186 extern void GL_Main_Init(void);
4187 extern void R_Shadow_Init(void);
4188 extern void R_Sky_Init(void);
4189 extern void GL_Surf_Init(void);
4190 extern void R_Particles_Init(void);
4191 extern void R_Explosion_Init(void);
4192 extern void gl_backend_init(void);
4193 extern void Sbar_Init(void);
4194 extern void R_LightningBeams_Init(void);
4195 extern void Mod_RenderInit(void);
4196 extern void Font_Init(void);
4197
4198 void Render_Init(void)
4199 {
4200         gl_backend_init();
4201         R_Textures_Init();
4202         GL_Main_Init();
4203         Font_Init();
4204         GL_Draw_Init();
4205         R_Shadow_Init();
4206         R_Sky_Init();
4207         GL_Surf_Init();
4208         Sbar_Init();
4209         R_Particles_Init();
4210         R_Explosion_Init();
4211         R_LightningBeams_Init();
4212         Mod_RenderInit();
4213 }
4214
4215 /*
4216 ===============
4217 GL_Init
4218 ===============
4219 */
4220 extern char *ENGINE_EXTENSIONS;
4221 void GL_Init (void)
4222 {
4223         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4224         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4225         gl_version = (const char *)qglGetString(GL_VERSION);
4226         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4227
4228         if (!gl_extensions)
4229                 gl_extensions = "";
4230         if (!gl_platformextensions)
4231                 gl_platformextensions = "";
4232
4233         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4234         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4235         Con_Printf("GL_VERSION: %s\n", gl_version);
4236         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4237         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4238
4239         VID_CheckExtensions();
4240
4241         // LordHavoc: report supported extensions
4242         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4243
4244         // clear to black (loading plaque will be seen over this)
4245         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4246 }
4247
4248 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4249 {
4250         int i;
4251         mplane_t *p;
4252         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4253         {
4254                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4255                 if (i == 4)
4256                         continue;
4257                 p = r_refdef.view.frustum + i;
4258                 switch(p->signbits)
4259                 {
4260                 default:
4261                 case 0:
4262                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4263                                 return true;
4264                         break;
4265                 case 1:
4266                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4267                                 return true;
4268                         break;
4269                 case 2:
4270                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4271                                 return true;
4272                         break;
4273                 case 3:
4274                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 4:
4278                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 5:
4282                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 case 6:
4286                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4287                                 return true;
4288                         break;
4289                 case 7:
4290                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4291                                 return true;
4292                         break;
4293                 }
4294         }
4295         return false;
4296 }
4297
4298 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4299 {
4300         int i;
4301         const mplane_t *p;
4302         for (i = 0;i < numplanes;i++)
4303         {
4304                 p = planes + i;
4305                 switch(p->signbits)
4306                 {
4307                 default:
4308                 case 0:
4309                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4310                                 return true;
4311                         break;
4312                 case 1:
4313                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4314                                 return true;
4315                         break;
4316                 case 2:
4317                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4318                                 return true;
4319                         break;
4320                 case 3:
4321                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 4:
4325                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 case 5:
4329                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4330                                 return true;
4331                         break;
4332                 case 6:
4333                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4334                                 return true;
4335                         break;
4336                 case 7:
4337                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4338                                 return true;
4339                         break;
4340                 }
4341         }
4342         return false;
4343 }
4344
4345 //==================================================================================
4346
4347 // LordHavoc: this stores temporary data used within the same frame
4348
4349 typedef struct r_framedata_mem_s
4350 {
4351         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4352         size_t size; // how much usable space
4353         size_t current; // how much space in use
4354         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4355         size_t wantedsize; // how much space was allocated
4356         unsigned char *data; // start of real data (16byte aligned)
4357 }
4358 r_framedata_mem_t;
4359
4360 static r_framedata_mem_t *r_framedata_mem;
4361
4362 void R_FrameData_Reset(void)
4363 {
4364         while (r_framedata_mem)
4365         {
4366                 r_framedata_mem_t *next = r_framedata_mem->purge;
4367                 Mem_Free(r_framedata_mem);
4368                 r_framedata_mem = next;
4369         }
4370 }
4371
4372 void R_FrameData_Resize(void)
4373 {
4374         size_t wantedsize;
4375         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4376         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4377         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4378         {
4379                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4380                 newmem->wantedsize = wantedsize;
4381                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4382                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4383                 newmem->current = 0;
4384                 newmem->mark = 0;
4385                 newmem->purge = r_framedata_mem;
4386                 r_framedata_mem = newmem;
4387         }
4388 }
4389
4390 void R_FrameData_NewFrame(void)
4391 {
4392         R_FrameData_Resize();
4393         if (!r_framedata_mem)
4394                 return;
4395         // if we ran out of space on the last frame, free the old memory now
4396         while (r_framedata_mem->purge)
4397         {
4398                 // repeatedly remove the second item in the list, leaving only head
4399                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4400                 Mem_Free(r_framedata_mem->purge);
4401                 r_framedata_mem->purge = next;
4402         }
4403         // reset the current mem pointer
4404         r_framedata_mem->current = 0;
4405         r_framedata_mem->mark = 0;
4406 }
4407
4408 void *R_FrameData_Alloc(size_t size)
4409 {
4410         void *data;
4411
4412         // align to 16 byte boundary - the data pointer is already aligned, so we
4413         // only need to ensure the size of every allocation is also aligned
4414         size = (size + 15) & ~15;
4415
4416         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4417         {
4418                 // emergency - we ran out of space, allocate more memory
4419                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4420                 R_FrameData_Resize();
4421         }
4422
4423         data = r_framedata_mem->data + r_framedata_mem->current;
4424         r_framedata_mem->current += size;
4425
4426         // count the usage for stats
4427         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4428         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4429
4430         return (void *)data;
4431 }
4432
4433 void *R_FrameData_Store(size_t size, void *data)
4434 {
4435         void *d = R_FrameData_Alloc(size);
4436         if (d && data)
4437                 memcpy(d, data, size);
4438         return d;
4439 }
4440
4441 void R_FrameData_SetMark(void)
4442 {
4443         if (!r_framedata_mem)
4444                 return;
4445         r_framedata_mem->mark = r_framedata_mem->current;
4446 }
4447
4448 void R_FrameData_ReturnToMark(void)
4449 {
4450         if (!r_framedata_mem)
4451                 return;
4452         r_framedata_mem->current = r_framedata_mem->mark;
4453 }
4454
4455 //==================================================================================
4456
4457 // LordHavoc: animcache originally written by Echon, rewritten since then
4458
4459 /**
4460  * Animation cache prevents re-generating mesh data for an animated model
4461  * multiple times in one frame for lighting, shadowing, reflections, etc.
4462  */
4463
4464 void R_AnimCache_Free(void)
4465 {
4466 }
4467
4468 void R_AnimCache_ClearCache(void)
4469 {
4470         int i;
4471         entity_render_t *ent;
4472
4473         for (i = 0;i < r_refdef.scene.numentities;i++)
4474         {
4475                 ent = r_refdef.scene.entities[i];
4476                 ent->animcache_vertex3f = NULL;
4477                 ent->animcache_normal3f = NULL;
4478                 ent->animcache_svector3f = NULL;
4479                 ent->animcache_tvector3f = NULL;
4480                 ent->animcache_vertexmesh = NULL;
4481                 ent->animcache_vertex3fbuffer = NULL;
4482                 ent->animcache_vertexmeshbuffer = NULL;
4483         }
4484 }
4485
4486 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4487 {
4488         int i;
4489
4490         // check if we need the meshbuffers
4491         if (!vid.useinterleavedarrays)
4492                 return;
4493
4494         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4495                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4496         // TODO: upload vertex3f buffer?
4497         if (ent->animcache_vertexmesh)
4498         {
4499                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4500                 for (i = 0;i < numvertices;i++)
4501                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4502                 if (ent->animcache_svector3f)
4503                         for (i = 0;i < numvertices;i++)
4504                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4505                 if (ent->animcache_tvector3f)
4506                         for (i = 0;i < numvertices;i++)
4507                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4508                 if (ent->animcache_normal3f)
4509                         for (i = 0;i < numvertices;i++)
4510                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4511                 // TODO: upload vertexmeshbuffer?
4512         }
4513 }
4514
4515 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4516 {
4517         dp_model_t *model = ent->model;
4518         int numvertices;
4519         // see if it's already cached this frame
4520         if (ent->animcache_vertex3f)
4521         {
4522                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4523                 if (wantnormals || wanttangents)
4524                 {
4525                         if (ent->animcache_normal3f)
4526                                 wantnormals = false;
4527                         if (ent->animcache_svector3f)
4528                                 wanttangents = false;
4529                         if (wantnormals || wanttangents)
4530                         {
4531                                 numvertices = model->surfmesh.num_vertices;
4532                                 if (wantnormals)
4533                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534                                 if (wanttangents)
4535                                 {
4536                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4537                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4538                                 }
4539                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4540                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4541                         }
4542                 }
4543         }
4544         else
4545         {
4546                 // see if this ent is worth caching
4547                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4548                         return false;
4549                 // get some memory for this entity and generate mesh data
4550                 numvertices = model->surfmesh.num_vertices;
4551                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4552                 if (wantnormals)
4553                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4554                 if (wanttangents)
4555                 {
4556                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4557                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4558                 }
4559                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4560                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4561         }
4562         return true;
4563 }
4564
4565 void R_AnimCache_CacheVisibleEntities(void)
4566 {
4567         int i;
4568         qboolean wantnormals = true;
4569         qboolean wanttangents = !r_showsurfaces.integer;
4570
4571         switch(vid.renderpath)
4572         {
4573         case RENDERPATH_GL20:
4574         case RENDERPATH_D3D9:
4575         case RENDERPATH_D3D10:
4576         case RENDERPATH_D3D11:
4577         case RENDERPATH_GLES2:
4578                 break;
4579         case RENDERPATH_GL13:
4580         case RENDERPATH_GL11:
4581                 wanttangents = false;
4582                 break;
4583         case RENDERPATH_SOFT:
4584                 break;
4585         }
4586
4587         if (r_shownormals.integer)
4588                 wanttangents = wantnormals = true;
4589
4590         // TODO: thread this
4591         // NOTE: R_PrepareRTLights() also caches entities
4592
4593         for (i = 0;i < r_refdef.scene.numentities;i++)
4594                 if (r_refdef.viewcache.entityvisible[i])
4595                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4596 }
4597
4598 //==================================================================================
4599
4600 static void R_View_UpdateEntityLighting (void)
4601 {
4602         int i;
4603         entity_render_t *ent;
4604         vec3_t tempdiffusenormal, avg;
4605         vec_t f, fa, fd, fdd;
4606         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4607
4608         for (i = 0;i < r_refdef.scene.numentities;i++)
4609         {
4610                 ent = r_refdef.scene.entities[i];
4611
4612                 // skip unseen models
4613                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4614                         continue;
4615
4616                 // skip bsp models
4617                 if (ent->model && ent->model->brush.num_leafs)
4618                 {
4619                         // TODO: use modellight for r_ambient settings on world?
4620                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4621                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4622                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4623                         continue;
4624                 }
4625
4626                 // fetch the lighting from the worldmodel data
4627                 VectorClear(ent->modellight_ambient);
4628                 VectorClear(ent->modellight_diffuse);
4629                 VectorClear(tempdiffusenormal);
4630                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4631                 {
4632                         vec3_t org;
4633                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4634
4635                         // complete lightning for lit sprites
4636                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4637                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4638                         {
4639                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4640                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4641                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4642                         }
4643                         else
4644                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4645
4646                         if(ent->flags & RENDER_EQUALIZE)
4647                         {
4648                                 // first fix up ambient lighting...
4649                                 if(r_equalize_entities_minambient.value > 0)
4650                                 {
4651                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4652                                         if(fd > 0)
4653                                         {
4654                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4655                                                 if(fa < r_equalize_entities_minambient.value * fd)
4656                                                 {
4657                                                         // solve:
4658                                                         //   fa'/fd' = minambient
4659                                                         //   fa'+0.25*fd' = fa+0.25*fd
4660                                                         //   ...
4661                                                         //   fa' = fd' * minambient
4662                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4663                                                         //   ...
4664                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4665                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4666                                                         //   ...
4667                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4668                                                         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
4669                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4670                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4671                                                 }
4672                                         }
4673                                 }
4674
4675                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4676                                 {
4677                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4678                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4679                                         f = fa + 0.25 * fd;
4680                                         if(f > 0)
4681                                         {
4682                                                 // adjust brightness and saturation to target
4683                                                 avg[0] = avg[1] = avg[2] = fa / f;
4684                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4685                                                 avg[0] = avg[1] = avg[2] = fd / f;
4686                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4687                                         }
4688                                 }
4689                         }
4690                 }
4691                 else // highly rare
4692                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4693
4694                 // move the light direction into modelspace coordinates for lighting code
4695                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4696                 if(VectorLength2(ent->modellight_lightdir) == 0)
4697                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4698                 VectorNormalize(ent->modellight_lightdir);
4699         }
4700 }
4701
4702 #define MAX_LINEOFSIGHTTRACES 64
4703
4704 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4705 {
4706         int i;
4707         vec3_t boxmins, boxmaxs;
4708         vec3_t start;
4709         vec3_t end;
4710         dp_model_t *model = r_refdef.scene.worldmodel;
4711
4712         if (!model || !model->brush.TraceLineOfSight)
4713                 return true;
4714
4715         // expand the box a little
4716         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4717         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4718         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4719         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4720         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4721         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4722
4723         // return true if eye is inside enlarged box
4724         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4725                 return true;
4726
4727         // try center
4728         VectorCopy(eye, start);
4729         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4730         if (model->brush.TraceLineOfSight(model, start, end))
4731                 return true;
4732
4733         // try various random positions
4734         for (i = 0;i < numsamples;i++)
4735         {
4736                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4737                 if (model->brush.TraceLineOfSight(model, start, end))
4738                         return true;
4739         }
4740
4741         return false;
4742 }
4743
4744
4745 static void R_View_UpdateEntityVisible (void)
4746 {
4747         int i;
4748         int renderimask;
4749         int samples;
4750         entity_render_t *ent;
4751
4752         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4753                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4754                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4755                 :                                                          RENDER_EXTERIORMODEL;
4756         if (!r_drawviewmodel.integer)
4757                 renderimask |= RENDER_VIEWMODEL;
4758         if (!r_drawexteriormodel.integer)
4759                 renderimask |= RENDER_EXTERIORMODEL;
4760         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4761         {
4762                 // worldmodel can check visibility
4763                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4764                 for (i = 0;i < r_refdef.scene.numentities;i++)
4765                 {
4766                         ent = r_refdef.scene.entities[i];
4767                         if (!(ent->flags & renderimask))
4768                         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)))
4769                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4770                                 r_refdef.viewcache.entityvisible[i] = true;
4771                 }
4772                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4773                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4774                 {
4775                         for (i = 0;i < r_refdef.scene.numentities;i++)
4776                         {
4777                                 ent = r_refdef.scene.entities[i];
4778                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4779                                 {
4780                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4781                                         if (samples < 0)
4782                                                 continue; // temp entities do pvs only
4783                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4784                                                 ent->last_trace_visibility = realtime;
4785                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4786                                                 r_refdef.viewcache.entityvisible[i] = 0;
4787                                 }
4788                         }
4789                 }
4790         }
4791         else
4792         {
4793                 // no worldmodel or it can't check visibility
4794                 for (i = 0;i < r_refdef.scene.numentities;i++)
4795                 {
4796                         ent = r_refdef.scene.entities[i];
4797                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4798                 }
4799         }
4800 }
4801
4802 /// only used if skyrendermasked, and normally returns false
4803 int R_DrawBrushModelsSky (void)
4804 {
4805         int i, sky;
4806         entity_render_t *ent;
4807
4808         sky = false;
4809         for (i = 0;i < r_refdef.scene.numentities;i++)
4810         {
4811                 if (!r_refdef.viewcache.entityvisible[i])
4812                         continue;
4813                 ent = r_refdef.scene.entities[i];
4814                 if (!ent->model || !ent->model->DrawSky)
4815                         continue;
4816                 ent->model->DrawSky(ent);
4817                 sky = true;
4818         }
4819         return sky;
4820 }
4821
4822 static void R_DrawNoModel(entity_render_t *ent);
4823 static void R_DrawModels(void)
4824 {
4825         int i;
4826         entity_render_t *ent;
4827
4828         for (i = 0;i < r_refdef.scene.numentities;i++)
4829         {
4830                 if (!r_refdef.viewcache.entityvisible[i])
4831                         continue;
4832                 ent = r_refdef.scene.entities[i];
4833                 r_refdef.stats.entities++;
4834                 if (ent->model && ent->model->Draw != NULL)
4835                         ent->model->Draw(ent);
4836                 else
4837                         R_DrawNoModel(ent);
4838         }
4839 }
4840
4841 static void R_DrawModelsDepth(void)
4842 {
4843         int i;
4844         entity_render_t *ent;
4845
4846         for (i = 0;i < r_refdef.scene.numentities;i++)
4847         {
4848                 if (!r_refdef.viewcache.entityvisible[i])
4849                         continue;
4850                 ent = r_refdef.scene.entities[i];
4851                 if (ent->model && ent->model->DrawDepth != NULL)
4852                         ent->model->DrawDepth(ent);
4853         }
4854 }
4855
4856 static void R_DrawModelsDebug(void)
4857 {
4858         int i;
4859         entity_render_t *ent;
4860
4861         for (i = 0;i < r_refdef.scene.numentities;i++)
4862         {
4863                 if (!r_refdef.viewcache.entityvisible[i])
4864                         continue;
4865                 ent = r_refdef.scene.entities[i];
4866                 if (ent->model && ent->model->DrawDebug != NULL)
4867                         ent->model->DrawDebug(ent);
4868         }
4869 }
4870
4871 static void R_DrawModelsAddWaterPlanes(void)
4872 {
4873         int i;
4874         entity_render_t *ent;
4875
4876         for (i = 0;i < r_refdef.scene.numentities;i++)
4877         {
4878                 if (!r_refdef.viewcache.entityvisible[i])
4879                         continue;
4880                 ent = r_refdef.scene.entities[i];
4881                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4882                         ent->model->DrawAddWaterPlanes(ent);
4883         }
4884 }
4885
4886 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4887 {
4888         if (r_hdr_irisadaptation.integer)
4889         {
4890                 vec3_t ambient;
4891                 vec3_t diffuse;
4892                 vec3_t diffusenormal;
4893                 vec_t brightness;
4894                 vec_t goal;
4895                 vec_t adjust;
4896                 vec_t current;
4897                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4898                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4899                 brightness = max(0.0000001f, brightness);
4900                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4901                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4902                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4903                 current = r_hdr_irisadaptation_value.value;
4904                 if (current < goal)
4905                         current = min(current + adjust, goal);
4906                 else if (current > goal)
4907                         current = max(current - adjust, goal);
4908                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4909                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4910         }
4911         else if (r_hdr_irisadaptation_value.value != 1.0f)
4912                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4913 }
4914
4915 static void R_View_SetFrustum(const int *scissor)
4916 {
4917         int i;
4918         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4919         vec3_t forward, left, up, origin, v;
4920
4921         if(scissor)
4922         {
4923                 // flipped x coordinates (because x points left here)
4924                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4925                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4926
4927                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4928                 switch(vid.renderpath)
4929                 {
4930                         case RENDERPATH_D3D9:
4931                         case RENDERPATH_D3D10:
4932                         case RENDERPATH_D3D11:
4933                         case RENDERPATH_SOFT:
4934                                 // non-flipped y coordinates
4935                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4936                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4937                                 break;
4938                         case RENDERPATH_GL11:
4939                         case RENDERPATH_GL13:
4940                         case RENDERPATH_GL20:
4941                         case RENDERPATH_GLES2:
4942                                 // non-flipped y coordinates
4943                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4945                                 break;
4946                 }
4947         }
4948
4949         // we can't trust r_refdef.view.forward and friends in reflected scenes
4950         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4951
4952 #if 0
4953         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4954         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4955         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4956         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4957         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4958         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4959         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4960         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4961         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4962         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4963         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4964         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4965 #endif
4966
4967 #if 0
4968         zNear = r_refdef.nearclip;
4969         nudge = 1.0 - 1.0 / (1<<23);
4970         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4971         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4972         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4973         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4974         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4975         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4976         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4977         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4978 #endif
4979
4980
4981
4982 #if 0
4983         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4984         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4985         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4986         r_refdef.view.frustum[0].dist = m[15] - m[12];
4987
4988         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4989         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4990         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4991         r_refdef.view.frustum[1].dist = m[15] + m[12];
4992
4993         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4994         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4995         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4996         r_refdef.view.frustum[2].dist = m[15] - m[13];
4997
4998         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4999         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5000         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5001         r_refdef.view.frustum[3].dist = m[15] + m[13];
5002
5003         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5004         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5005         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5006         r_refdef.view.frustum[4].dist = m[15] - m[14];
5007
5008         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5009         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5010         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5011         r_refdef.view.frustum[5].dist = m[15] + m[14];
5012 #endif
5013
5014         if (r_refdef.view.useperspective)
5015         {
5016                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5017                 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]);
5018                 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]);
5019                 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]);
5020                 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]);
5021
5022                 // then the normals from the corners relative to origin
5023                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5024                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5025                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5026                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5027
5028                 // in a NORMAL view, forward cross left == up
5029                 // in a REFLECTED view, forward cross left == down
5030                 // so our cross products above need to be adjusted for a left handed coordinate system
5031                 CrossProduct(forward, left, v);
5032                 if(DotProduct(v, up) < 0)
5033                 {
5034                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5035                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5036                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5037                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5038                 }
5039
5040                 // Leaving those out was a mistake, those were in the old code, and they
5041                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5042                 // I couldn't reproduce it after adding those normalizations. --blub
5043                 VectorNormalize(r_refdef.view.frustum[0].normal);
5044                 VectorNormalize(r_refdef.view.frustum[1].normal);
5045                 VectorNormalize(r_refdef.view.frustum[2].normal);
5046                 VectorNormalize(r_refdef.view.frustum[3].normal);
5047
5048                 // make the corners absolute
5049                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5050                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5051                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5052                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5053
5054                 // one more normal
5055                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5056
5057                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5058                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5059                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5060                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5061                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5062         }
5063         else
5064         {
5065                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5066                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5067                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5068                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5069                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5070                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5071                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5072                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5073                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5074                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5075         }
5076         r_refdef.view.numfrustumplanes = 5;
5077
5078         if (r_refdef.view.useclipplane)
5079         {
5080                 r_refdef.view.numfrustumplanes = 6;
5081                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5082         }
5083
5084         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5085                 PlaneClassify(r_refdef.view.frustum + i);
5086
5087         // LordHavoc: note to all quake engine coders, Quake had a special case
5088         // for 90 degrees which assumed a square view (wrong), so I removed it,
5089         // Quake2 has it disabled as well.
5090
5091         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5092         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5093         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5094         //PlaneClassify(&frustum[0]);
5095
5096         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5097         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5098         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5099         //PlaneClassify(&frustum[1]);
5100
5101         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5102         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5103         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5104         //PlaneClassify(&frustum[2]);
5105
5106         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5107         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5108         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5109         //PlaneClassify(&frustum[3]);
5110
5111         // nearclip plane
5112         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5113         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5114         //PlaneClassify(&frustum[4]);
5115 }
5116
5117 void R_View_UpdateWithScissor(const int *myscissor)
5118 {
5119         R_Main_ResizeViewCache();
5120         R_View_SetFrustum(myscissor);
5121         R_View_WorldVisibility(r_refdef.view.useclipplane);
5122         R_View_UpdateEntityVisible();
5123         R_View_UpdateEntityLighting();
5124 }
5125
5126 void R_View_Update(void)
5127 {
5128         R_Main_ResizeViewCache();
5129         R_View_SetFrustum(NULL);
5130         R_View_WorldVisibility(r_refdef.view.useclipplane);
5131         R_View_UpdateEntityVisible();
5132         R_View_UpdateEntityLighting();
5133 }
5134
5135 float viewscalefpsadjusted = 1.0f;
5136
5137 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5138 {
5139         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5140         scale = bound(0.03125f, scale, 1.0f);
5141         *outwidth = (int)ceil(width * scale);
5142         *outheight = (int)ceil(height * scale);
5143 }
5144
5145 void R_Mesh_SetMainRenderTargets(void)
5146 {
5147         if (r_bloomstate.fbo_framebuffer)
5148                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5149         else
5150                 R_Mesh_ResetRenderTargets();
5151 }
5152
5153 void R_SetupView(qboolean allowwaterclippingplane)
5154 {
5155         const float *customclipplane = NULL;
5156         float plane[4];
5157         int scaledwidth, scaledheight;
5158         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5159         {
5160                 // LordHavoc: couldn't figure out how to make this approach the
5161                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5162                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5163                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5164                         dist = r_refdef.view.clipplane.dist;
5165                 plane[0] = r_refdef.view.clipplane.normal[0];
5166                 plane[1] = r_refdef.view.clipplane.normal[1];
5167                 plane[2] = r_refdef.view.clipplane.normal[2];
5168                 plane[3] = dist;
5169                 customclipplane = plane;
5170         }
5171
5172         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5173         if (!r_refdef.view.useperspective)
5174                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - 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);
5175         else if (vid.stencil && r_useinfinitefarclip.integer)
5176                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5177         else
5178                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5179         R_Mesh_SetMainRenderTargets();
5180         R_SetViewport(&r_refdef.view.viewport);
5181 }
5182
5183 void R_EntityMatrix(const matrix4x4_t *matrix)
5184 {
5185         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5186         {
5187                 gl_modelmatrixchanged = false;
5188                 gl_modelmatrix = *matrix;
5189                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5190                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5191                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5192                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5193                 CHECKGLERROR
5194                 switch(vid.renderpath)
5195                 {
5196                 case RENDERPATH_D3D9:
5197 #ifdef SUPPORTD3D
5198                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5199                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5200 #endif
5201                         break;
5202                 case RENDERPATH_D3D10:
5203                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5204                         break;
5205                 case RENDERPATH_D3D11:
5206                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5207                         break;
5208                 case RENDERPATH_GL13:
5209                 case RENDERPATH_GL11:
5210                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5211                         break;
5212                 case RENDERPATH_SOFT:
5213                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5214                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5215                         break;
5216                 case RENDERPATH_GL20:
5217                 case RENDERPATH_GLES2:
5218                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5219                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5220                         break;
5221                 }
5222         }
5223 }
5224
5225 void R_ResetViewRendering2D(void)
5226 {
5227         r_viewport_t viewport;
5228         DrawQ_Finish();
5229
5230         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5231         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, 1, 1, -10, 100, NULL);
5232         R_Mesh_ResetRenderTargets();
5233         R_SetViewport(&viewport);
5234         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5235         GL_Color(1, 1, 1, 1);
5236         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5237         GL_BlendFunc(GL_ONE, GL_ZERO);
5238         GL_ScissorTest(false);
5239         GL_DepthMask(false);
5240         GL_DepthRange(0, 1);
5241         GL_DepthTest(false);
5242         GL_DepthFunc(GL_LEQUAL);
5243         R_EntityMatrix(&identitymatrix);
5244         R_Mesh_ResetTextureState();
5245         GL_PolygonOffset(0, 0);
5246         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5247         switch(vid.renderpath)
5248         {
5249         case RENDERPATH_GL11:
5250         case RENDERPATH_GL13:
5251         case RENDERPATH_GL20:
5252         case RENDERPATH_GLES2:
5253                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5254                 break;
5255         case RENDERPATH_D3D9:
5256         case RENDERPATH_D3D10:
5257         case RENDERPATH_D3D11:
5258         case RENDERPATH_SOFT:
5259                 break;
5260         }
5261         GL_CullFace(GL_NONE);
5262 }
5263
5264 void R_ResetViewRendering3D(void)
5265 {
5266         DrawQ_Finish();
5267
5268         R_SetupView(true);
5269         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5270         GL_Color(1, 1, 1, 1);
5271         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5272         GL_BlendFunc(GL_ONE, GL_ZERO);
5273         GL_ScissorTest(true);
5274         GL_DepthMask(true);
5275         GL_DepthRange(0, 1);
5276         GL_DepthTest(true);
5277         GL_DepthFunc(GL_LEQUAL);
5278         R_EntityMatrix(&identitymatrix);
5279         R_Mesh_ResetTextureState();
5280         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5281         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5282         switch(vid.renderpath)
5283         {
5284         case RENDERPATH_GL11:
5285         case RENDERPATH_GL13:
5286         case RENDERPATH_GL20:
5287         case RENDERPATH_GLES2:
5288                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5289                 break;
5290         case RENDERPATH_D3D9:
5291         case RENDERPATH_D3D10:
5292         case RENDERPATH_D3D11:
5293         case RENDERPATH_SOFT:
5294                 break;
5295         }
5296         GL_CullFace(r_refdef.view.cullface_back);
5297 }
5298
5299 /*
5300 ================
5301 R_RenderView_UpdateViewVectors
5302 ================
5303 */
5304 static void R_RenderView_UpdateViewVectors(void)
5305 {
5306         // break apart the view matrix into vectors for various purposes
5307         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5308         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5309         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5310         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5311         // make an inverted copy of the view matrix for tracking sprites
5312         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5313 }
5314
5315 void R_RenderScene(void);
5316 void R_RenderWaterPlanes(void);
5317
5318 static void R_Water_StartFrame(void)
5319 {
5320         int i;
5321         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5322         r_waterstate_waterplane_t *p;
5323
5324         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5325                 return;
5326
5327         switch(vid.renderpath)
5328         {
5329         case RENDERPATH_GL20:
5330         case RENDERPATH_D3D9:
5331         case RENDERPATH_D3D10:
5332         case RENDERPATH_D3D11:
5333         case RENDERPATH_SOFT:
5334         case RENDERPATH_GLES2:
5335                 break;
5336         case RENDERPATH_GL13:
5337         case RENDERPATH_GL11:
5338                 return;
5339         }
5340
5341         // set waterwidth and waterheight to the water resolution that will be
5342         // used (often less than the screen resolution for faster rendering)
5343         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5344         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5345
5346         // calculate desired texture sizes
5347         // can't use water if the card does not support the texture size
5348         if (!r_water.integer || r_showsurfaces.integer)
5349                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5350         else if (vid.support.arb_texture_non_power_of_two)
5351         {
5352                 texturewidth = waterwidth;
5353                 textureheight = waterheight;
5354                 camerawidth = waterwidth;
5355                 cameraheight = waterheight;
5356         }
5357         else
5358         {
5359                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5360                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5361                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5362                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5363         }
5364
5365         // allocate textures as needed
5366         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5367         {
5368                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5369                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5370                 {
5371                         if (p->texture_refraction)
5372                                 R_FreeTexture(p->texture_refraction);
5373                         p->texture_refraction = NULL;
5374                         if (p->texture_reflection)
5375                                 R_FreeTexture(p->texture_reflection);
5376                         p->texture_reflection = NULL;
5377                         if (p->texture_camera)
5378                                 R_FreeTexture(p->texture_camera);
5379                         p->texture_camera = NULL;
5380                 }
5381                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5382                 r_waterstate.texturewidth = texturewidth;
5383                 r_waterstate.textureheight = textureheight;
5384                 r_waterstate.camerawidth = camerawidth;
5385                 r_waterstate.cameraheight = cameraheight;
5386         }
5387
5388         if (r_waterstate.texturewidth)
5389         {
5390                 r_waterstate.enabled = true;
5391
5392                 // when doing a reduced render (HDR) we want to use a smaller area
5393                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5394                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5395
5396                 // set up variables that will be used in shader setup
5397                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5398                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5399                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5400                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5401         }
5402
5403         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5404         r_waterstate.numwaterplanes = 0;
5405 }
5406
5407 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5408 {
5409         int triangleindex, planeindex;
5410         const int *e;
5411         vec3_t vert[3];
5412         vec3_t normal;
5413         vec3_t center;
5414         mplane_t plane;
5415         r_waterstate_waterplane_t *p;
5416         texture_t *t = R_GetCurrentTexture(surface->texture);
5417
5418         // just use the first triangle with a valid normal for any decisions
5419         VectorClear(normal);
5420         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5421         {
5422                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5423                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5424                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5425                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5426                 if (VectorLength2(normal) >= 0.001)
5427                         break;
5428         }
5429
5430         VectorCopy(normal, plane.normal);
5431         VectorNormalize(plane.normal);
5432         plane.dist = DotProduct(vert[0], plane.normal);
5433         PlaneClassify(&plane);
5434         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5435         {
5436                 // skip backfaces (except if nocullface is set)
5437                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5438                         return;
5439                 VectorNegate(plane.normal, plane.normal);
5440                 plane.dist *= -1;
5441                 PlaneClassify(&plane);
5442         }
5443
5444
5445         // find a matching plane if there is one
5446         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5447                 if(p->camera_entity == t->camera_entity)
5448                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5449                                 break;
5450         if (planeindex >= r_waterstate.maxwaterplanes)
5451                 return; // nothing we can do, out of planes
5452
5453         // if this triangle does not fit any known plane rendered this frame, add one
5454         if (planeindex >= r_waterstate.numwaterplanes)
5455         {
5456                 // store the new plane
5457                 r_waterstate.numwaterplanes++;
5458                 p->plane = plane;
5459                 // clear materialflags and pvs
5460                 p->materialflags = 0;
5461                 p->pvsvalid = false;
5462                 p->camera_entity = t->camera_entity;
5463                 VectorCopy(surface->mins, p->mins);
5464                 VectorCopy(surface->maxs, p->maxs);
5465         }
5466         else
5467         {
5468                 // merge mins/maxs
5469                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5470                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5471                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5472                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5473                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5474                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5475         }
5476         // merge this surface's materialflags into the waterplane
5477         p->materialflags |= t->currentmaterialflags;
5478         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5479         {
5480                 // merge this surface's PVS into the waterplane
5481                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5482                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5483                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5484                 {
5485                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5486                         p->pvsvalid = true;
5487                 }
5488         }
5489 }
5490
5491 static void R_Water_ProcessPlanes(void)
5492 {
5493         int myscissor[4];
5494         r_refdef_view_t originalview;
5495         r_refdef_view_t myview;
5496         int planeindex;
5497         r_waterstate_waterplane_t *p;
5498         vec3_t visorigin;
5499
5500         originalview = r_refdef.view;
5501
5502         // make sure enough textures are allocated
5503         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5504         {
5505                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5506                 {
5507                         if (!p->texture_refraction)
5508                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5509                         if (!p->texture_refraction)
5510                                 goto error;
5511                 }
5512                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5513                 {
5514                         if (!p->texture_camera)
5515                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5516                         if (!p->texture_camera)
5517                                 goto error;
5518                 }
5519
5520                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5521                 {
5522                         if (!p->texture_reflection)
5523                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5524                         if (!p->texture_reflection)
5525                                 goto error;
5526                 }
5527         }
5528
5529         // render views
5530         r_refdef.view = originalview;
5531         r_refdef.view.showdebug = false;
5532         r_refdef.view.width = r_waterstate.waterwidth;
5533         r_refdef.view.height = r_waterstate.waterheight;
5534         r_refdef.view.useclipplane = true;
5535         myview = r_refdef.view;
5536         r_waterstate.renderingscene = true;
5537         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5538         {
5539                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5540                 {
5541                         r_refdef.view = myview;
5542                         if(r_water_scissormode.integer)
5543                         {
5544                                 R_SetupView(true);
5545                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5546                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5547                         }
5548
5549                         // render reflected scene and copy into texture
5550                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5551                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5552                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5553                         r_refdef.view.clipplane = p->plane;
5554
5555                         // reverse the cullface settings for this render
5556                         r_refdef.view.cullface_front = GL_FRONT;
5557                         r_refdef.view.cullface_back = GL_BACK;
5558                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5559                         {
5560                                 r_refdef.view.usecustompvs = true;
5561                                 if (p->pvsvalid)
5562                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5563                                 else
5564                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5565                         }
5566
5567                         R_ResetViewRendering3D();
5568                         R_ClearScreen(r_refdef.fogenabled);
5569                         if(r_water_scissormode.integer & 2)
5570                                 R_View_UpdateWithScissor(myscissor);
5571                         else
5572                                 R_View_Update();
5573                         if(r_water_scissormode.integer & 1)
5574                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5575                         R_RenderScene();
5576
5577                         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);
5578                 }
5579
5580                 // render the normal view scene and copy into texture
5581                 // (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)
5582                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5583                 {
5584                         r_refdef.view = myview;
5585                         if(r_water_scissormode.integer)
5586                         {
5587                                 R_SetupView(true);
5588                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5589                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5590                         }
5591
5592                         r_waterstate.renderingrefraction = true;
5593
5594                         r_refdef.view.clipplane = p->plane;
5595                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5596                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5597
5598                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5599                         {
5600                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5601                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5602                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5603                                 R_RenderView_UpdateViewVectors();
5604                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5605                                 {
5606                                         r_refdef.view.usecustompvs = true;
5607                                         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);
5608                                 }
5609                         }
5610
5611                         PlaneClassify(&r_refdef.view.clipplane);
5612
5613                         R_ResetViewRendering3D();
5614                         R_ClearScreen(r_refdef.fogenabled);
5615                         if(r_water_scissormode.integer & 2)
5616                                 R_View_UpdateWithScissor(myscissor);
5617                         else
5618                                 R_View_Update();
5619                         if(r_water_scissormode.integer & 1)
5620                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5621                         R_RenderScene();
5622
5623                         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);
5624                         r_waterstate.renderingrefraction = false;
5625                 }
5626                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5627                 {
5628                         r_refdef.view = myview;
5629
5630                         r_refdef.view.clipplane = p->plane;
5631                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5632                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5633
5634                         r_refdef.view.width = r_waterstate.camerawidth;
5635                         r_refdef.view.height = r_waterstate.cameraheight;
5636                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5637                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5638
5639                         if(p->camera_entity)
5640                         {
5641                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5642                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5643                         }
5644
5645                         // note: all of the view is used for displaying... so
5646                         // there is no use in scissoring
5647
5648                         // reverse the cullface settings for this render
5649                         r_refdef.view.cullface_front = GL_FRONT;
5650                         r_refdef.view.cullface_back = GL_BACK;
5651                         // also reverse the view matrix
5652                         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
5653                         R_RenderView_UpdateViewVectors();
5654                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5655                         {
5656                                 r_refdef.view.usecustompvs = true;
5657                                 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);
5658                         }
5659                         
5660                         // camera needs no clipplane
5661                         r_refdef.view.useclipplane = false;
5662
5663                         PlaneClassify(&r_refdef.view.clipplane);
5664
5665                         R_ResetViewRendering3D();
5666                         R_ClearScreen(r_refdef.fogenabled);
5667                         R_View_Update();
5668                         R_RenderScene();
5669
5670                         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);
5671                         r_waterstate.renderingrefraction = false;
5672                 }
5673
5674         }
5675         r_waterstate.renderingscene = false;
5676         r_refdef.view = originalview;
5677         R_ResetViewRendering3D();
5678         R_ClearScreen(r_refdef.fogenabled);
5679         R_View_Update();
5680         return;
5681 error:
5682         r_refdef.view = originalview;
5683         r_waterstate.renderingscene = false;
5684         Cvar_SetValueQuick(&r_water, 0);
5685         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5686         return;
5687 }
5688
5689 void R_Bloom_StartFrame(void)
5690 {
5691         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5692         int viewwidth, viewheight;
5693         textype_t textype;
5694
5695         if (r_viewscale_fpsscaling.integer)
5696         {
5697                 double actualframetime;
5698                 double targetframetime;
5699                 double adjust;
5700                 actualframetime = r_refdef.lastdrawscreentime;
5701                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5702                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5703                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5704                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5705                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5706                 viewscalefpsadjusted += adjust;
5707                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5708         }
5709         else
5710                 viewscalefpsadjusted = 1.0f;
5711
5712         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5713
5714         switch(vid.renderpath)
5715         {
5716         case RENDERPATH_GL20:
5717         case RENDERPATH_D3D9:
5718         case RENDERPATH_D3D10:
5719         case RENDERPATH_D3D11:
5720         case RENDERPATH_SOFT:
5721         case RENDERPATH_GLES2:
5722                 break;
5723         case RENDERPATH_GL13:
5724         case RENDERPATH_GL11:
5725                 return;
5726         }
5727
5728         // set bloomwidth and bloomheight to the bloom resolution that will be
5729         // used (often less than the screen resolution for faster rendering)
5730         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5731         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5732         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5733         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5734         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5735
5736         // calculate desired texture sizes
5737         if (vid.support.arb_texture_non_power_of_two)
5738         {
5739                 screentexturewidth = vid.width;
5740                 screentextureheight = vid.height;
5741                 bloomtexturewidth = r_bloomstate.bloomwidth;
5742                 bloomtextureheight = r_bloomstate.bloomheight;
5743         }
5744         else
5745         {
5746                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5747                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5748                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5749                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5750         }
5751
5752         if ((r_hdr.integer || 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))
5753         {
5754                 Cvar_SetValueQuick(&r_hdr, 0);
5755                 Cvar_SetValueQuick(&r_bloom, 0);
5756                 Cvar_SetValueQuick(&r_motionblur, 0);
5757                 Cvar_SetValueQuick(&r_damageblur, 0);
5758         }
5759
5760         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5761                 screentexturewidth = screentextureheight = 0;
5762         if (!r_hdr.integer && !r_bloom.integer)
5763                 bloomtexturewidth = bloomtextureheight = 0;
5764
5765         textype = TEXTYPE_COLORBUFFER;
5766         switch (vid.renderpath)
5767         {
5768         case RENDERPATH_GL20:
5769         case RENDERPATH_GLES2:
5770                 if (vid.support.ext_framebuffer_object)
5771                 {
5772                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5773                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5774                 }
5775                 break;
5776         case RENDERPATH_D3D9:
5777         case RENDERPATH_D3D10:
5778         case RENDERPATH_D3D11:
5779         case RENDERPATH_SOFT:
5780         case RENDERPATH_GL13:
5781         case RENDERPATH_GL11:
5782                 break;
5783         }
5784
5785         // allocate textures as needed
5786         if (r_bloomstate.screentexturewidth != screentexturewidth
5787          || r_bloomstate.screentextureheight != screentextureheight
5788          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5789          || r_bloomstate.bloomtextureheight != bloomtextureheight
5790          || r_bloomstate.texturetype != textype
5791          || r_bloomstate.viewfbo != r_viewfbo.integer)
5792         {
5793                 if (r_bloomstate.texture_bloom)
5794                         R_FreeTexture(r_bloomstate.texture_bloom);
5795                 r_bloomstate.texture_bloom = NULL;
5796                 if (r_bloomstate.texture_screen)
5797                         R_FreeTexture(r_bloomstate.texture_screen);
5798                 r_bloomstate.texture_screen = NULL;
5799                 if (r_bloomstate.fbo_framebuffer)
5800                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5801                 r_bloomstate.fbo_framebuffer = 0;
5802                 if (r_bloomstate.texture_framebuffercolor)
5803                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5804                 r_bloomstate.texture_framebuffercolor = NULL;
5805                 if (r_bloomstate.texture_framebufferdepth)
5806                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5807                 r_bloomstate.texture_framebufferdepth = NULL;
5808                 r_bloomstate.screentexturewidth = screentexturewidth;
5809                 r_bloomstate.screentextureheight = screentextureheight;
5810                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5811                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5812                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5813                 {
5814                         // FIXME: choose depth bits based on a cvar
5815                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5816                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5817                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5818                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5819                         // render depth into one texture and normalmap into the other
5820                         if (qglDrawBuffer)
5821                         {
5822                                 int status;
5823                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5824                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5825                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5826                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5827                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5828                         }
5829                 }
5830                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5831                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5832                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5833                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5834                 r_bloomstate.viewfbo = r_viewfbo.integer;
5835                 r_bloomstate.texturetype = textype;
5836         }
5837
5838         // when doing a reduced render (HDR) we want to use a smaller area
5839         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5840         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5841         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5842         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5843         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5844
5845         // set up a texcoord array for the full resolution screen image
5846         // (we have to keep this around to copy back during final render)
5847         r_bloomstate.screentexcoord2f[0] = 0;
5848         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5849         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5850         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5851         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5852         r_bloomstate.screentexcoord2f[5] = 0;
5853         r_bloomstate.screentexcoord2f[6] = 0;
5854         r_bloomstate.screentexcoord2f[7] = 0;
5855
5856         // set up a texcoord array for the reduced resolution bloom image
5857         // (which will be additive blended over the screen image)
5858         r_bloomstate.bloomtexcoord2f[0] = 0;
5859         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5860         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5861         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5862         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5863         r_bloomstate.bloomtexcoord2f[5] = 0;
5864         r_bloomstate.bloomtexcoord2f[6] = 0;
5865         r_bloomstate.bloomtexcoord2f[7] = 0;
5866
5867         switch(vid.renderpath)
5868         {
5869         case RENDERPATH_GL11:
5870         case RENDERPATH_GL13:
5871         case RENDERPATH_GL20:
5872         case RENDERPATH_SOFT:
5873         case RENDERPATH_GLES2:
5874                 break;
5875         case RENDERPATH_D3D9:
5876         case RENDERPATH_D3D10:
5877         case RENDERPATH_D3D11:
5878                 {
5879                         int i;
5880                         for (i = 0;i < 4;i++)
5881                         {
5882                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5883                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5884                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5885                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5886                         }
5887                 }
5888                 break;
5889         }
5890
5891         if (r_hdr.integer || r_bloom.integer)
5892         {
5893                 r_bloomstate.enabled = true;
5894                 r_bloomstate.hdr = r_hdr.integer != 0;
5895         }
5896
5897         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5898
5899         if (r_bloomstate.fbo_framebuffer)
5900                 r_refdef.view.clear = true;
5901 }
5902
5903 void R_Bloom_CopyBloomTexture(float colorscale)
5904 {
5905         r_refdef.stats.bloom++;
5906
5907         // scale down screen texture to the bloom texture size
5908         CHECKGLERROR
5909         R_Mesh_SetMainRenderTargets();
5910         R_SetViewport(&r_bloomstate.viewport);
5911         GL_BlendFunc(GL_ONE, GL_ZERO);
5912         GL_Color(colorscale, colorscale, colorscale, 1);
5913         // 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...
5914         switch(vid.renderpath)
5915         {
5916         case RENDERPATH_GL11:
5917         case RENDERPATH_GL13:
5918         case RENDERPATH_GL20:
5919         case RENDERPATH_SOFT:
5920         case RENDERPATH_GLES2:
5921                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5922                 break;
5923         case RENDERPATH_D3D9:
5924         case RENDERPATH_D3D10:
5925         case RENDERPATH_D3D11:
5926                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5927                 break;
5928         }
5929         // TODO: do boxfilter scale-down in shader?
5930         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5931         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5932         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5933
5934         // we now have a bloom image in the framebuffer
5935         // copy it into the bloom image texture for later processing
5936         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5937         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5938 }
5939
5940 void R_Bloom_CopyHDRTexture(void)
5941 {
5942         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5943         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5944 }
5945
5946 void R_Bloom_MakeTexture(void)
5947 {
5948         int x, range, dir;
5949         float xoffset, yoffset, r, brighten;
5950
5951         r_refdef.stats.bloom++;
5952
5953         R_ResetViewRendering2D();
5954
5955         // we have a bloom image in the framebuffer
5956         CHECKGLERROR
5957         R_SetViewport(&r_bloomstate.viewport);
5958
5959         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5960         {
5961                 x *= 2;
5962                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5963                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5964                 GL_Color(r,r,r,1);
5965                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5966                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5967                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5968                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5969
5970                 // copy the vertically blurred bloom view to a texture
5971                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5972                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5973         }
5974
5975         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5976         brighten = r_bloom_brighten.value;
5977         if (r_hdr.integer)
5978                 brighten *= r_hdr_range.value;
5979         brighten = sqrt(brighten);
5980         if(range >= 1)
5981                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5982         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5983
5984         for (dir = 0;dir < 2;dir++)
5985         {
5986                 // blend on at multiple vertical offsets to achieve a vertical blur
5987                 // TODO: do offset blends using GLSL
5988                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5989                 GL_BlendFunc(GL_ONE, GL_ZERO);
5990                 for (x = -range;x <= range;x++)
5991                 {
5992                         if (!dir){xoffset = 0;yoffset = x;}
5993                         else {xoffset = x;yoffset = 0;}
5994                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5995                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5996                         // compute a texcoord array with the specified x and y offset
5997                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5998                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5999                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6000                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6001                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6002                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6003                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6004                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6005                         // this r value looks like a 'dot' particle, fading sharply to
6006                         // black at the edges
6007                         // (probably not realistic but looks good enough)
6008                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6009                         //r = brighten/(range*2+1);
6010                         r = brighten / (range * 2 + 1);
6011                         if(range >= 1)
6012                                 r *= (1 - x*x/(float)(range*range));
6013                         GL_Color(r, r, r, 1);
6014                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6015                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6016                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6017                         GL_BlendFunc(GL_ONE, GL_ONE);
6018                 }
6019
6020                 // copy the vertically blurred bloom view to a texture
6021                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6022                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6023         }
6024 }
6025
6026 void R_HDR_RenderBloomTexture(void)
6027 {
6028         int oldwidth, oldheight;
6029         float oldcolorscale;
6030         qboolean oldwaterstate;
6031
6032         oldwaterstate = r_waterstate.enabled;
6033         oldcolorscale = r_refdef.view.colorscale;
6034         oldwidth = r_refdef.view.width;
6035         oldheight = r_refdef.view.height;
6036         r_refdef.view.width = r_bloomstate.bloomwidth;
6037         r_refdef.view.height = r_bloomstate.bloomheight;
6038
6039         if(r_hdr.integer < 2)
6040                 r_waterstate.enabled = false;
6041
6042         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6043         // TODO: add exposure compensation features
6044         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6045
6046         r_refdef.view.showdebug = false;
6047         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6048
6049         R_ResetViewRendering3D();
6050
6051         R_ClearScreen(r_refdef.fogenabled);
6052         if (r_timereport_active)
6053                 R_TimeReport("HDRclear");
6054
6055         R_View_Update();
6056         if (r_timereport_active)
6057                 R_TimeReport("visibility");
6058
6059         // only do secondary renders with HDR if r_hdr is 2 or higher
6060         r_waterstate.numwaterplanes = 0;
6061         if (r_waterstate.enabled)
6062                 R_RenderWaterPlanes();
6063
6064         r_refdef.view.showdebug = true;
6065         R_RenderScene();
6066         r_waterstate.numwaterplanes = 0;
6067
6068         R_ResetViewRendering2D();
6069
6070         R_Bloom_CopyHDRTexture();
6071         R_Bloom_MakeTexture();
6072
6073         // restore the view settings
6074         r_waterstate.enabled = oldwaterstate;
6075         r_refdef.view.width = oldwidth;
6076         r_refdef.view.height = oldheight;
6077         r_refdef.view.colorscale = oldcolorscale;
6078
6079         R_ResetViewRendering3D();
6080
6081         R_ClearScreen(r_refdef.fogenabled);
6082         if (r_timereport_active)
6083                 R_TimeReport("viewclear");
6084 }
6085
6086 static void R_BlendView(void)
6087 {
6088         unsigned int permutation;
6089         float uservecs[4][4];
6090
6091         switch (vid.renderpath)
6092         {
6093         case RENDERPATH_GL20:
6094         case RENDERPATH_D3D9:
6095         case RENDERPATH_D3D10:
6096         case RENDERPATH_D3D11:
6097         case RENDERPATH_SOFT:
6098         case RENDERPATH_GLES2:
6099                 permutation =
6100                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6101                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6102                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6103                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6104                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6105
6106                 if (r_bloomstate.texture_screen)
6107                 {
6108                         // make sure the buffer is available
6109                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6110
6111                         R_ResetViewRendering2D();
6112                         R_Mesh_SetMainRenderTargets();
6113
6114                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6115                         {
6116                                 // declare variables
6117                                 float speed;
6118                                 static float avgspeed;
6119
6120                                 speed = VectorLength(cl.movement_velocity);
6121
6122                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6123                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6124
6125                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6126                                 speed = bound(0, speed, 1);
6127                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6128
6129                                 // calculate values into a standard alpha
6130                                 cl.motionbluralpha = 1 - exp(-
6131                                                 (
6132                                                  (r_motionblur.value * speed / 80)
6133                                                  +
6134                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6135                                                 )
6136                                                 /
6137                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6138                                            );
6139
6140                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6141                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6142                                 // apply the blur
6143                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6144                                 {
6145                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6146                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6147                                         switch(vid.renderpath)
6148                                         {
6149                                         case RENDERPATH_GL11:
6150                                         case RENDERPATH_GL13:
6151                                         case RENDERPATH_GL20:
6152                                         case RENDERPATH_SOFT:
6153                                         case RENDERPATH_GLES2:
6154                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6155                                                 break;
6156                                         case RENDERPATH_D3D9:
6157                                         case RENDERPATH_D3D10:
6158                                         case RENDERPATH_D3D11:
6159                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6160                                                 break;
6161                                         }
6162                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6163                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6164                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6165                                 }
6166                         }
6167
6168                         // copy view into the screen texture
6169                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6170                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6171                 }
6172                 else if (!r_bloomstate.texture_bloom)
6173                 {
6174                         // we may still have to do view tint...
6175                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6176                         {
6177                                 // apply a color tint to the whole view
6178                                 R_ResetViewRendering2D();
6179                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6180                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6181                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6182                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6183                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6184                         }
6185                         break; // no screen processing, no bloom, skip it
6186                 }
6187
6188                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6189                 {
6190                         // render simple bloom effect
6191                         // copy the screen and shrink it and darken it for the bloom process
6192                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6193                         // make the bloom texture
6194                         R_Bloom_MakeTexture();
6195                 }
6196
6197 #if _MSC_VER >= 1400
6198 #define sscanf sscanf_s
6199 #endif
6200                 memset(uservecs, 0, sizeof(uservecs));
6201                 if (r_glsl_postprocess_uservec1_enable.integer)
6202                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6203                 if (r_glsl_postprocess_uservec2_enable.integer)
6204                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6205                 if (r_glsl_postprocess_uservec3_enable.integer)
6206                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6207                 if (r_glsl_postprocess_uservec4_enable.integer)
6208                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6209
6210                 R_ResetViewRendering2D();
6211                 GL_Color(1, 1, 1, 1);
6212                 GL_BlendFunc(GL_ONE, GL_ZERO);
6213
6214                 switch(vid.renderpath)
6215                 {
6216                 case RENDERPATH_GL20:
6217                 case RENDERPATH_GLES2:
6218                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6219                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6220                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6221                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6222                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6223                         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]);
6224                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6225                         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]);
6226                         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]);
6227                         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]);
6228                         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]);
6229                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6230                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6231                         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);
6232                         break;
6233                 case RENDERPATH_D3D9:
6234 #ifdef SUPPORTD3D
6235                         // 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...
6236                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6237                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6238                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6239                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6240                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6241                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6242                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6243                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6244                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6245                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6246                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6247                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6248                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6249                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6250 #endif
6251                         break;
6252                 case RENDERPATH_D3D10:
6253                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6254                         break;
6255                 case RENDERPATH_D3D11:
6256                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6257                         break;
6258                 case RENDERPATH_SOFT:
6259                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6260                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6261                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6262                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6263                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6264                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6265                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6266                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6267                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6268                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6269                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6270                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6271                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6272                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6273                         break;
6274                 default:
6275                         break;
6276                 }
6277                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6279                 break;
6280         case RENDERPATH_GL13:
6281         case RENDERPATH_GL11:
6282                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6283                 {
6284                         // apply a color tint to the whole view
6285                         R_ResetViewRendering2D();
6286                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6287                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6288                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6289                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6290                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6291                 }
6292                 break;
6293         }
6294 }
6295
6296 matrix4x4_t r_waterscrollmatrix;
6297
6298 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6299 {
6300         if (r_refdef.fog_density)
6301         {
6302                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6303                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6304                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6305
6306                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6307                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6308                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6309                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6310
6311                 {
6312                         vec3_t fogvec;
6313                         VectorCopy(r_refdef.fogcolor, fogvec);
6314                         //   color.rgb *= ContrastBoost * SceneBrightness;
6315                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6316                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6317                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6318                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6319                 }
6320         }
6321 }
6322
6323 void R_UpdateVariables(void)
6324 {
6325         R_Textures_Frame();
6326
6327         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6328
6329         r_refdef.farclip = r_farclip_base.value;
6330         if (r_refdef.scene.worldmodel)
6331                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6332         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6333
6334         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6335                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6336         r_refdef.polygonfactor = 0;
6337         r_refdef.polygonoffset = 0;
6338         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6339         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6340
6341         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6342         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6343         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6344         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6345         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6346         if (FAKELIGHT_ENABLED)
6347         {
6348                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6349         }
6350         if (r_showsurfaces.integer)
6351         {
6352                 r_refdef.scene.rtworld = false;
6353                 r_refdef.scene.rtworldshadows = false;
6354                 r_refdef.scene.rtdlight = false;
6355                 r_refdef.scene.rtdlightshadows = false;
6356                 r_refdef.lightmapintensity = 0;
6357         }
6358
6359         if (gamemode == GAME_NEHAHRA)
6360         {
6361                 if (gl_fogenable.integer)
6362                 {
6363                         r_refdef.oldgl_fogenable = true;
6364                         r_refdef.fog_density = gl_fogdensity.value;
6365                         r_refdef.fog_red = gl_fogred.value;
6366                         r_refdef.fog_green = gl_foggreen.value;
6367                         r_refdef.fog_blue = gl_fogblue.value;
6368                         r_refdef.fog_alpha = 1;
6369                         r_refdef.fog_start = 0;
6370                         r_refdef.fog_end = gl_skyclip.value;
6371                         r_refdef.fog_height = 1<<30;
6372                         r_refdef.fog_fadedepth = 128;
6373                 }
6374                 else if (r_refdef.oldgl_fogenable)
6375                 {
6376                         r_refdef.oldgl_fogenable = false;
6377                         r_refdef.fog_density = 0;
6378                         r_refdef.fog_red = 0;
6379                         r_refdef.fog_green = 0;
6380                         r_refdef.fog_blue = 0;
6381                         r_refdef.fog_alpha = 0;
6382                         r_refdef.fog_start = 0;
6383                         r_refdef.fog_end = 0;
6384                         r_refdef.fog_height = 1<<30;
6385                         r_refdef.fog_fadedepth = 128;
6386                 }
6387         }
6388
6389         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6390         r_refdef.fog_start = max(0, r_refdef.fog_start);
6391         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6392
6393         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6394
6395         if (r_refdef.fog_density && r_drawfog.integer)
6396         {
6397                 r_refdef.fogenabled = true;
6398                 // this is the point where the fog reaches 0.9986 alpha, which we
6399                 // consider a good enough cutoff point for the texture
6400                 // (0.9986 * 256 == 255.6)
6401                 if (r_fog_exp2.integer)
6402                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6403                 else
6404                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6405                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6406                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6407                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6408                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6409                         R_BuildFogHeightTexture();
6410                 // fog color was already set
6411                 // update the fog texture
6412                 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)
6413                         R_BuildFogTexture();
6414                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6415                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6416         }
6417         else
6418                 r_refdef.fogenabled = false;
6419
6420         switch(vid.renderpath)
6421         {
6422         case RENDERPATH_GL20:
6423         case RENDERPATH_D3D9:
6424         case RENDERPATH_D3D10:
6425         case RENDERPATH_D3D11:
6426         case RENDERPATH_SOFT:
6427         case RENDERPATH_GLES2:
6428                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6429                 {
6430                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6431                         {
6432                                 // build GLSL gamma texture
6433 #define RAMPWIDTH 256
6434                                 unsigned short ramp[RAMPWIDTH * 3];
6435                                 unsigned char rampbgr[RAMPWIDTH][4];
6436                                 int i;
6437
6438                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6439
6440                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6441                                 for(i = 0; i < RAMPWIDTH; ++i)
6442                                 {
6443                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6444                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6445                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6446                                         rampbgr[i][3] = 0;
6447                                 }
6448                                 if (r_texture_gammaramps)
6449                                 {
6450                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6451                                 }
6452                                 else
6453                                 {
6454                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6455                                 }
6456                         }
6457                 }
6458                 else
6459                 {
6460                         // remove GLSL gamma texture
6461                 }
6462                 break;
6463         case RENDERPATH_GL13:
6464         case RENDERPATH_GL11:
6465                 break;
6466         }
6467 }
6468
6469 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6470 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6471 /*
6472 ================
6473 R_SelectScene
6474 ================
6475 */
6476 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6477         if( scenetype != r_currentscenetype ) {
6478                 // store the old scenetype
6479                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6480                 r_currentscenetype = scenetype;
6481                 // move in the new scene
6482                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6483         }
6484 }
6485
6486 /*
6487 ================
6488 R_GetScenePointer
6489 ================
6490 */
6491 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6492 {
6493         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6494         if( scenetype == r_currentscenetype ) {
6495                 return &r_refdef.scene;
6496         } else {
6497                 return &r_scenes_store[ scenetype ];
6498         }
6499 }
6500
6501 /*
6502 ================
6503 R_RenderView
6504 ================
6505 */
6506 int dpsoftrast_test;
6507 void R_RenderView(void)
6508 {
6509         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6510
6511         dpsoftrast_test = r_test.integer;
6512
6513         if (r_timereport_active)
6514                 R_TimeReport("start");
6515         r_textureframe++; // used only by R_GetCurrentTexture
6516         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6517
6518         if(R_CompileShader_CheckStaticParms())
6519                 R_GLSL_Restart_f();
6520
6521         if (!r_drawentities.integer)
6522                 r_refdef.scene.numentities = 0;
6523
6524         R_AnimCache_ClearCache();
6525         R_FrameData_NewFrame();
6526
6527         /* adjust for stereo display */
6528         if(R_Stereo_Active())
6529         {
6530                 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);
6531                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6532         }
6533
6534         if (r_refdef.view.isoverlay)
6535         {
6536                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6537                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6538                 R_TimeReport("depthclear");
6539
6540                 r_refdef.view.showdebug = false;
6541
6542                 r_waterstate.enabled = false;
6543                 r_waterstate.numwaterplanes = 0;
6544
6545                 R_RenderScene();
6546
6547                 r_refdef.view.matrix = originalmatrix;
6548
6549                 CHECKGLERROR
6550                 return;
6551         }
6552
6553         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6554         {
6555                 r_refdef.view.matrix = originalmatrix;
6556                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6557         }
6558
6559         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6560
6561         R_RenderView_UpdateViewVectors();
6562
6563         R_Shadow_UpdateWorldLightSelection();
6564
6565         R_Bloom_StartFrame();
6566         R_Water_StartFrame();
6567
6568         CHECKGLERROR
6569         if (r_timereport_active)
6570                 R_TimeReport("viewsetup");
6571
6572         R_ResetViewRendering3D();
6573
6574         if (r_refdef.view.clear || r_refdef.fogenabled)
6575         {
6576                 R_ClearScreen(r_refdef.fogenabled);
6577                 if (r_timereport_active)
6578                         R_TimeReport("viewclear");
6579         }
6580         r_refdef.view.clear = true;
6581
6582         // this produces a bloom texture to be used in R_BlendView() later
6583         if (r_hdr.integer && r_bloomstate.bloomwidth)
6584         {
6585                 R_HDR_RenderBloomTexture();
6586                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6587                 r_textureframe++; // used only by R_GetCurrentTexture
6588         }
6589
6590         r_refdef.view.showdebug = true;
6591
6592         R_View_Update();
6593         if (r_timereport_active)
6594                 R_TimeReport("visibility");
6595
6596         r_waterstate.numwaterplanes = 0;
6597         if (r_waterstate.enabled)
6598                 R_RenderWaterPlanes();
6599
6600         R_RenderScene();
6601         r_waterstate.numwaterplanes = 0;
6602
6603         R_BlendView();
6604         if (r_timereport_active)
6605                 R_TimeReport("blendview");
6606
6607         GL_Scissor(0, 0, vid.width, vid.height);
6608         GL_ScissorTest(false);
6609
6610         r_refdef.view.matrix = originalmatrix;
6611
6612         CHECKGLERROR
6613 }
6614
6615 void R_RenderWaterPlanes(void)
6616 {
6617         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6618         {
6619                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6620                 if (r_timereport_active)
6621                         R_TimeReport("waterworld");
6622         }
6623
6624         // don't let sound skip if going slow
6625         if (r_refdef.scene.extraupdate)
6626                 S_ExtraUpdate ();
6627
6628         R_DrawModelsAddWaterPlanes();
6629         if (r_timereport_active)
6630                 R_TimeReport("watermodels");
6631
6632         if (r_waterstate.numwaterplanes)
6633         {
6634                 R_Water_ProcessPlanes();
6635                 if (r_timereport_active)
6636                         R_TimeReport("waterscenes");
6637         }
6638 }
6639
6640 extern void R_DrawLightningBeams (void);
6641 extern void VM_CL_AddPolygonsToMeshQueue (void);
6642 extern void R_DrawPortals (void);
6643 extern cvar_t cl_locs_show;
6644 static void R_DrawLocs(void);
6645 static void R_DrawEntityBBoxes(void);
6646 static void R_DrawModelDecals(void);
6647 extern void R_DrawModelShadows(void);
6648 extern void R_DrawModelShadowMaps(void);
6649 extern cvar_t cl_decals_newsystem;
6650 extern qboolean r_shadow_usingdeferredprepass;
6651 void R_RenderScene(void)
6652 {
6653         qboolean shadowmapping = false;
6654
6655         if (r_timereport_active)
6656                 R_TimeReport("beginscene");
6657
6658         r_refdef.stats.renders++;
6659
6660         R_UpdateFogColor();
6661
6662         // don't let sound skip if going slow
6663         if (r_refdef.scene.extraupdate)
6664                 S_ExtraUpdate ();
6665
6666         R_MeshQueue_BeginScene();
6667
6668         R_SkyStartFrame();
6669
6670         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);
6671
6672         if (r_timereport_active)
6673                 R_TimeReport("skystartframe");
6674
6675         if (cl.csqc_vidvars.drawworld)
6676         {
6677                 // don't let sound skip if going slow
6678                 if (r_refdef.scene.extraupdate)
6679                         S_ExtraUpdate ();
6680
6681                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6682                 {
6683                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6684                         if (r_timereport_active)
6685                                 R_TimeReport("worldsky");
6686                 }
6687
6688                 if (R_DrawBrushModelsSky() && r_timereport_active)
6689                         R_TimeReport("bmodelsky");
6690
6691                 if (skyrendermasked && skyrenderlater)
6692                 {
6693                         // we have to force off the water clipping plane while rendering sky
6694                         R_SetupView(false);
6695                         R_Sky();
6696                         R_SetupView(true);
6697                         if (r_timereport_active)
6698                                 R_TimeReport("sky");
6699                 }
6700         }
6701
6702         R_AnimCache_CacheVisibleEntities();
6703         if (r_timereport_active)
6704                 R_TimeReport("animation");
6705
6706         R_Shadow_PrepareLights();
6707         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6708                 R_Shadow_PrepareModelShadows();
6709         if (r_timereport_active)
6710                 R_TimeReport("preparelights");
6711
6712         if (R_Shadow_ShadowMappingEnabled())
6713                 shadowmapping = true;
6714
6715         if (r_shadow_usingdeferredprepass)
6716                 R_Shadow_DrawPrepass();
6717
6718         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6719         {
6720                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6721                 if (r_timereport_active)
6722                         R_TimeReport("worlddepth");
6723         }
6724         if (r_depthfirst.integer >= 2)
6725         {
6726                 R_DrawModelsDepth();
6727                 if (r_timereport_active)
6728                         R_TimeReport("modeldepth");
6729         }
6730
6731         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6732         {
6733                 R_DrawModelShadowMaps();
6734                 R_ResetViewRendering3D();
6735                 // don't let sound skip if going slow
6736                 if (r_refdef.scene.extraupdate)
6737                         S_ExtraUpdate ();
6738         }
6739
6740         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6741         {
6742                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6743                 if (r_timereport_active)
6744                         R_TimeReport("world");
6745         }
6746
6747         // don't let sound skip if going slow
6748         if (r_refdef.scene.extraupdate)
6749                 S_ExtraUpdate ();
6750
6751         R_DrawModels();
6752         if (r_timereport_active)
6753                 R_TimeReport("models");
6754
6755         // don't let sound skip if going slow
6756         if (r_refdef.scene.extraupdate)
6757                 S_ExtraUpdate ();
6758
6759         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6760         {
6761                 R_DrawModelShadows();
6762                 R_ResetViewRendering3D();
6763                 // don't let sound skip if going slow
6764                 if (r_refdef.scene.extraupdate)
6765                         S_ExtraUpdate ();
6766         }
6767
6768         if (!r_shadow_usingdeferredprepass)
6769         {
6770                 R_Shadow_DrawLights();
6771                 if (r_timereport_active)
6772                         R_TimeReport("rtlights");
6773         }
6774
6775         // don't let sound skip if going slow
6776         if (r_refdef.scene.extraupdate)
6777                 S_ExtraUpdate ();
6778
6779         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6780         {
6781                 R_DrawModelShadows();
6782                 R_ResetViewRendering3D();
6783                 // don't let sound skip if going slow
6784                 if (r_refdef.scene.extraupdate)
6785                         S_ExtraUpdate ();
6786         }
6787
6788         if (cl.csqc_vidvars.drawworld)
6789         {
6790                 if (cl_decals_newsystem.integer)
6791                 {
6792                         R_DrawModelDecals();
6793                         if (r_timereport_active)
6794                                 R_TimeReport("modeldecals");
6795                 }
6796                 else
6797                 {
6798                         R_DrawDecals();
6799                         if (r_timereport_active)
6800                                 R_TimeReport("decals");
6801                 }
6802
6803                 R_DrawParticles();
6804                 if (r_timereport_active)
6805                         R_TimeReport("particles");
6806
6807                 R_DrawExplosions();
6808                 if (r_timereport_active)
6809                         R_TimeReport("explosions");
6810
6811                 R_DrawLightningBeams();
6812                 if (r_timereport_active)
6813                         R_TimeReport("lightning");
6814         }
6815
6816         VM_CL_AddPolygonsToMeshQueue();
6817
6818         if (r_refdef.view.showdebug)
6819         {
6820                 if (cl_locs_show.integer)
6821                 {
6822                         R_DrawLocs();
6823                         if (r_timereport_active)
6824                                 R_TimeReport("showlocs");
6825                 }
6826
6827                 if (r_drawportals.integer)
6828                 {
6829                         R_DrawPortals();
6830                         if (r_timereport_active)
6831                                 R_TimeReport("portals");
6832                 }
6833
6834                 if (r_showbboxes.value > 0)
6835                 {
6836                         R_DrawEntityBBoxes();
6837                         if (r_timereport_active)
6838                                 R_TimeReport("bboxes");
6839                 }
6840         }
6841
6842         R_MeshQueue_RenderTransparent();
6843         if (r_timereport_active)
6844                 R_TimeReport("drawtrans");
6845
6846         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))
6847         {
6848                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6849                 if (r_timereport_active)
6850                         R_TimeReport("worlddebug");
6851                 R_DrawModelsDebug();
6852                 if (r_timereport_active)
6853                         R_TimeReport("modeldebug");
6854         }
6855
6856         if (cl.csqc_vidvars.drawworld)
6857         {
6858                 R_Shadow_DrawCoronas();
6859                 if (r_timereport_active)
6860                         R_TimeReport("coronas");
6861         }
6862
6863 #if 0
6864         {
6865                 GL_DepthTest(false);
6866                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6867                 GL_Color(1, 1, 1, 1);
6868                 qglBegin(GL_POLYGON);
6869                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6870                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6871                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6872                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6873                 qglEnd();
6874                 qglBegin(GL_POLYGON);
6875                 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]);
6876                 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]);
6877                 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]);
6878                 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]);
6879                 qglEnd();
6880                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6881         }
6882 #endif
6883
6884         // don't let sound skip if going slow
6885         if (r_refdef.scene.extraupdate)
6886                 S_ExtraUpdate ();
6887
6888         R_ResetViewRendering2D();
6889 }
6890
6891 static const unsigned short bboxelements[36] =
6892 {
6893         5, 1, 3, 5, 3, 7,
6894         6, 2, 0, 6, 0, 4,
6895         7, 3, 2, 7, 2, 6,
6896         4, 0, 1, 4, 1, 5,
6897         4, 5, 7, 4, 7, 6,
6898         1, 0, 2, 1, 2, 3,
6899 };
6900
6901 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6902 {
6903         int i;
6904         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6905
6906         RSurf_ActiveWorldEntity();
6907
6908         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6909         GL_DepthMask(false);
6910         GL_DepthRange(0, 1);
6911         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6912 //      R_Mesh_ResetTextureState();
6913
6914         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6915         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6916         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6917         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6918         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6919         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6920         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6921         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6922         R_FillColors(color4f, 8, cr, cg, cb, ca);
6923         if (r_refdef.fogenabled)
6924         {
6925                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6926                 {
6927                         f1 = RSurf_FogVertex(v);
6928                         f2 = 1 - f1;
6929                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6930                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6931                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6932                 }
6933         }
6934         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6935         R_Mesh_ResetTextureState();
6936         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6937         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6938 }
6939
6940 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6941 {
6942         int i;
6943         float color[4];
6944         prvm_edict_t *edict;
6945         prvm_prog_t *prog_save = prog;
6946
6947         // this function draws bounding boxes of server entities
6948         if (!sv.active)
6949                 return;
6950
6951         GL_CullFace(GL_NONE);
6952         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6953
6954         prog = 0;
6955         SV_VM_Begin();
6956         for (i = 0;i < numsurfaces;i++)
6957         {
6958                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6959                 switch ((int)edict->fields.server->solid)
6960                 {
6961                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6962                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6963                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6964                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6965                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6966                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6967                 }
6968                 color[3] *= r_showbboxes.value;
6969                 color[3] = bound(0, color[3], 1);
6970                 GL_DepthTest(!r_showdisabledepthtest.integer);
6971                 GL_CullFace(r_refdef.view.cullface_front);
6972                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6973         }
6974         SV_VM_End();
6975         prog = prog_save;
6976 }
6977
6978 static void R_DrawEntityBBoxes(void)
6979 {
6980         int i;
6981         prvm_edict_t *edict;
6982         vec3_t center;
6983         prvm_prog_t *prog_save = prog;
6984
6985         // this function draws bounding boxes of server entities
6986         if (!sv.active)
6987                 return;
6988
6989         prog = 0;
6990         SV_VM_Begin();
6991         for (i = 0;i < prog->num_edicts;i++)
6992         {
6993                 edict = PRVM_EDICT_NUM(i);
6994                 if (edict->priv.server->free)
6995                         continue;
6996                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6997                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6998                         continue;
6999                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7000                         continue;
7001                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7002                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7003         }
7004         SV_VM_End();
7005         prog = prog_save;
7006 }
7007
7008 static const int nomodelelement3i[24] =
7009 {
7010         5, 2, 0,
7011         5, 1, 2,
7012         5, 0, 3,
7013         5, 3, 1,
7014         0, 2, 4,
7015         2, 1, 4,
7016         3, 0, 4,
7017         1, 3, 4
7018 };
7019
7020 static const unsigned short nomodelelement3s[24] =
7021 {
7022         5, 2, 0,
7023         5, 1, 2,
7024         5, 0, 3,
7025         5, 3, 1,
7026         0, 2, 4,
7027         2, 1, 4,
7028         3, 0, 4,
7029         1, 3, 4
7030 };
7031
7032 static const float nomodelvertex3f[6*3] =
7033 {
7034         -16,   0,   0,
7035          16,   0,   0,
7036           0, -16,   0,
7037           0,  16,   0,
7038           0,   0, -16,
7039           0,   0,  16
7040 };
7041
7042 static const float nomodelcolor4f[6*4] =
7043 {
7044         0.0f, 0.0f, 0.5f, 1.0f,
7045         0.0f, 0.0f, 0.5f, 1.0f,
7046         0.0f, 0.5f, 0.0f, 1.0f,
7047         0.0f, 0.5f, 0.0f, 1.0f,
7048         0.5f, 0.0f, 0.0f, 1.0f,
7049         0.5f, 0.0f, 0.0f, 1.0f
7050 };
7051
7052 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7053 {
7054         int i;
7055         float f1, f2, *c;
7056         float color4f[6*4];
7057
7058         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);
7059
7060         // this is only called once per entity so numsurfaces is always 1, and
7061         // surfacelist is always {0}, so this code does not handle batches
7062
7063         if (rsurface.ent_flags & RENDER_ADDITIVE)
7064         {
7065                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7066                 GL_DepthMask(false);
7067         }
7068         else if (rsurface.colormod[3] < 1)
7069         {
7070                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7071                 GL_DepthMask(false);
7072         }
7073         else
7074         {
7075                 GL_BlendFunc(GL_ONE, GL_ZERO);
7076                 GL_DepthMask(true);
7077         }
7078         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7079         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7080         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7081         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7082         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7083         for (i = 0, c = color4f;i < 6;i++, c += 4)
7084         {
7085                 c[0] *= rsurface.colormod[0];
7086                 c[1] *= rsurface.colormod[1];
7087                 c[2] *= rsurface.colormod[2];
7088                 c[3] *= rsurface.colormod[3];
7089         }
7090         if (r_refdef.fogenabled)
7091         {
7092                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7093                 {
7094                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7095                         f2 = 1 - f1;
7096                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7097                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7098                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7099                 }
7100         }
7101 //      R_Mesh_ResetTextureState();
7102         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7103         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7104         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7105 }
7106
7107 void R_DrawNoModel(entity_render_t *ent)
7108 {
7109         vec3_t org;
7110         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7111         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7112                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7113         else
7114                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7115 }
7116
7117 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7118 {
7119         vec3_t right1, right2, diff, normal;
7120
7121         VectorSubtract (org2, org1, normal);
7122
7123         // calculate 'right' vector for start
7124         VectorSubtract (r_refdef.view.origin, org1, diff);
7125         CrossProduct (normal, diff, right1);
7126         VectorNormalize (right1);
7127
7128         // calculate 'right' vector for end
7129         VectorSubtract (r_refdef.view.origin, org2, diff);
7130         CrossProduct (normal, diff, right2);
7131         VectorNormalize (right2);
7132
7133         vert[ 0] = org1[0] + width * right1[0];
7134         vert[ 1] = org1[1] + width * right1[1];
7135         vert[ 2] = org1[2] + width * right1[2];
7136         vert[ 3] = org1[0] - width * right1[0];
7137         vert[ 4] = org1[1] - width * right1[1];
7138         vert[ 5] = org1[2] - width * right1[2];
7139         vert[ 6] = org2[0] - width * right2[0];
7140         vert[ 7] = org2[1] - width * right2[1];
7141         vert[ 8] = org2[2] - width * right2[2];
7142         vert[ 9] = org2[0] + width * right2[0];
7143         vert[10] = org2[1] + width * right2[1];
7144         vert[11] = org2[2] + width * right2[2];
7145 }
7146
7147 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)
7148 {
7149         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7150         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7151         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7152         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7153         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7154         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7155         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7156         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7157         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7158         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7159         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7160         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7161 }
7162
7163 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7164 {
7165         int i;
7166         float *vertex3f;
7167         float v[3];
7168         VectorSet(v, x, y, z);
7169         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7170                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7171                         break;
7172         if (i == mesh->numvertices)
7173         {
7174                 if (mesh->numvertices < mesh->maxvertices)
7175                 {
7176                         VectorCopy(v, vertex3f);
7177                         mesh->numvertices++;
7178                 }
7179                 return mesh->numvertices;
7180         }
7181         else
7182                 return i;
7183 }
7184
7185 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7186 {
7187         int i;
7188         int *e, element[3];
7189         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7190         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7191         e = mesh->element3i + mesh->numtriangles * 3;
7192         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7193         {
7194                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7195                 if (mesh->numtriangles < mesh->maxtriangles)
7196                 {
7197                         *e++ = element[0];
7198                         *e++ = element[1];
7199                         *e++ = element[2];
7200                         mesh->numtriangles++;
7201                 }
7202                 element[1] = element[2];
7203         }
7204 }
7205
7206 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7207 {
7208         int i;
7209         int *e, element[3];
7210         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7211         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7212         e = mesh->element3i + mesh->numtriangles * 3;
7213         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7214         {
7215                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7216                 if (mesh->numtriangles < mesh->maxtriangles)
7217                 {
7218                         *e++ = element[0];
7219                         *e++ = element[1];
7220                         *e++ = element[2];
7221                         mesh->numtriangles++;
7222                 }
7223                 element[1] = element[2];
7224         }
7225 }
7226
7227 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7228 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7229 {
7230         int planenum, planenum2;
7231         int w;
7232         int tempnumpoints;
7233         mplane_t *plane, *plane2;
7234         double maxdist;
7235         double temppoints[2][256*3];
7236         // figure out how large a bounding box we need to properly compute this brush
7237         maxdist = 0;
7238         for (w = 0;w < numplanes;w++)
7239                 maxdist = max(maxdist, fabs(planes[w].dist));
7240         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7241         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7242         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7243         {
7244                 w = 0;
7245                 tempnumpoints = 4;
7246                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7247                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7248                 {
7249                         if (planenum2 == planenum)
7250                                 continue;
7251                         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);
7252                         w = !w;
7253                 }
7254                 if (tempnumpoints < 3)
7255                         continue;
7256                 // generate elements forming a triangle fan for this polygon
7257                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7258         }
7259 }
7260
7261 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)
7262 {
7263         texturelayer_t *layer;
7264         layer = t->currentlayers + t->currentnumlayers++;
7265         layer->type = type;
7266         layer->depthmask = depthmask;
7267         layer->blendfunc1 = blendfunc1;
7268         layer->blendfunc2 = blendfunc2;
7269         layer->texture = texture;
7270         layer->texmatrix = *matrix;
7271         layer->color[0] = r;
7272         layer->color[1] = g;
7273         layer->color[2] = b;
7274         layer->color[3] = a;
7275 }
7276
7277 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7278 {
7279         if(parms[0] == 0 && parms[1] == 0)
7280                 return false;
7281         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7282                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7283                         return false;
7284         return true;
7285 }
7286
7287 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7288 {
7289         double index, f;
7290         index = parms[2] + r_refdef.scene.time * parms[3];
7291         index -= floor(index);
7292         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7293         {
7294         default:
7295         case Q3WAVEFUNC_NONE:
7296         case Q3WAVEFUNC_NOISE:
7297         case Q3WAVEFUNC_COUNT:
7298                 f = 0;
7299                 break;
7300         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7301         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7302         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7303         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7304         case Q3WAVEFUNC_TRIANGLE:
7305                 index *= 4;
7306                 f = index - floor(index);
7307                 if (index < 1)
7308                         f = f;
7309                 else if (index < 2)
7310                         f = 1 - f;
7311                 else if (index < 3)
7312                         f = -f;
7313                 else
7314                         f = -(1 - f);
7315                 break;
7316         }
7317         f = parms[0] + parms[1] * f;
7318         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7319                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7320         return (float) f;
7321 }
7322
7323 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7324 {
7325         int w, h, idx;
7326         float f;
7327         float tcmat[12];
7328         matrix4x4_t matrix, temp;
7329         switch(tcmod->tcmod)
7330         {
7331                 case Q3TCMOD_COUNT:
7332                 case Q3TCMOD_NONE:
7333                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7334                                 matrix = r_waterscrollmatrix;
7335                         else
7336                                 matrix = identitymatrix;
7337                         break;
7338                 case Q3TCMOD_ENTITYTRANSLATE:
7339                         // this is used in Q3 to allow the gamecode to control texcoord
7340                         // scrolling on the entity, which is not supported in darkplaces yet.
7341                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7342                         break;
7343                 case Q3TCMOD_ROTATE:
7344                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7345                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7346                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7347                         break;
7348                 case Q3TCMOD_SCALE:
7349                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7350                         break;
7351                 case Q3TCMOD_SCROLL:
7352                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7353                         break;
7354                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7355                         w = (int) tcmod->parms[0];
7356                         h = (int) tcmod->parms[1];
7357                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7358                         f = f - floor(f);
7359                         idx = (int) floor(f * w * h);
7360                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7361                         break;
7362                 case Q3TCMOD_STRETCH:
7363                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7364                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7365                         break;
7366                 case Q3TCMOD_TRANSFORM:
7367                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7368                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7369                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7370                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7371                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7372                         break;
7373                 case Q3TCMOD_TURBULENT:
7374                         // this is handled in the RSurf_PrepareVertices function
7375                         matrix = identitymatrix;
7376                         break;
7377         }
7378         temp = *texmatrix;
7379         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7380 }
7381
7382 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7383 {
7384         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7385         char name[MAX_QPATH];
7386         skinframe_t *skinframe;
7387         unsigned char pixels[296*194];
7388         strlcpy(cache->name, skinname, sizeof(cache->name));
7389         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7390         if (developer_loading.integer)
7391                 Con_Printf("loading %s\n", name);
7392         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7393         if (!skinframe || !skinframe->base)
7394         {
7395                 unsigned char *f;
7396                 fs_offset_t filesize;
7397                 skinframe = NULL;
7398                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7399                 if (f)
7400                 {
7401                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7402                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7403                         Mem_Free(f);
7404                 }
7405         }
7406         cache->skinframe = skinframe;
7407 }
7408
7409 texture_t *R_GetCurrentTexture(texture_t *t)
7410 {
7411         int i;
7412         const entity_render_t *ent = rsurface.entity;
7413         dp_model_t *model = ent->model;
7414         q3shaderinfo_layer_tcmod_t *tcmod;
7415
7416         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7417                 return t->currentframe;
7418         t->update_lastrenderframe = r_textureframe;
7419         t->update_lastrenderentity = (void *)ent;
7420
7421         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7422                 t->camera_entity = ent->entitynumber;
7423         else
7424                 t->camera_entity = 0;
7425
7426         // switch to an alternate material if this is a q1bsp animated material
7427         {
7428                 texture_t *texture = t;
7429                 int s = rsurface.ent_skinnum;
7430                 if ((unsigned int)s >= (unsigned int)model->numskins)
7431                         s = 0;
7432                 if (model->skinscenes)
7433                 {
7434                         if (model->skinscenes[s].framecount > 1)
7435                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7436                         else
7437                                 s = model->skinscenes[s].firstframe;
7438                 }
7439                 if (s > 0)
7440                         t = t + s * model->num_surfaces;
7441                 if (t->animated)
7442                 {
7443                         // use an alternate animation if the entity's frame is not 0,
7444                         // and only if the texture has an alternate animation
7445                         if (rsurface.ent_alttextures && t->anim_total[1])
7446                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7447                         else
7448                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7449                 }
7450                 texture->currentframe = t;
7451         }
7452
7453         // update currentskinframe to be a qw skin or animation frame
7454         if (rsurface.ent_qwskin >= 0)
7455         {
7456                 i = rsurface.ent_qwskin;
7457                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7458                 {
7459                         r_qwskincache_size = cl.maxclients;
7460                         if (r_qwskincache)
7461                                 Mem_Free(r_qwskincache);
7462                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7463                 }
7464                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7465                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7466                 t->currentskinframe = r_qwskincache[i].skinframe;
7467                 if (t->currentskinframe == NULL)
7468                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7469         }
7470         else if (t->numskinframes >= 2)
7471                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7472         if (t->backgroundnumskinframes >= 2)
7473                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7474
7475         t->currentmaterialflags = t->basematerialflags;
7476         t->currentalpha = rsurface.colormod[3];
7477         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7478                 t->currentalpha *= r_wateralpha.value;
7479         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7480                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7481         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7482                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7483         if (!(rsurface.ent_flags & RENDER_LIGHT))
7484                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7485         else if (FAKELIGHT_ENABLED)
7486         {
7487                         // no modellight if using fakelight for the map
7488         }
7489         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7490         {
7491                 // pick a model lighting mode
7492                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7493                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7494                 else
7495                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7496         }
7497         if (rsurface.ent_flags & RENDER_ADDITIVE)
7498                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7499         else if (t->currentalpha < 1)
7500                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7501         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7502                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7503         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7504                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7505         if (t->backgroundnumskinframes)
7506                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7507         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7508         {
7509                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7510                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7511         }
7512         else
7513                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7514         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7515                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7516
7517         // there is no tcmod
7518         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7519         {
7520                 t->currenttexmatrix = r_waterscrollmatrix;
7521                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7522         }
7523         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7524         {
7525                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7526                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7527         }
7528
7529         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7530                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7531         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7532                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7533
7534         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7535         if (t->currentskinframe->qpixels)
7536                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7537         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7538         if (!t->basetexture)
7539                 t->basetexture = r_texture_notexture;
7540         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7541         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7542         t->nmaptexture = t->currentskinframe->nmap;
7543         if (!t->nmaptexture)
7544                 t->nmaptexture = r_texture_blanknormalmap;
7545         t->glosstexture = r_texture_black;
7546         t->glowtexture = t->currentskinframe->glow;
7547         t->fogtexture = t->currentskinframe->fog;
7548         t->reflectmasktexture = t->currentskinframe->reflect;
7549         if (t->backgroundnumskinframes)
7550         {
7551                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7552                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7553                 t->backgroundglosstexture = r_texture_black;
7554                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7555                 if (!t->backgroundnmaptexture)
7556                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7557         }
7558         else
7559         {
7560                 t->backgroundbasetexture = r_texture_white;
7561                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7562                 t->backgroundglosstexture = r_texture_black;
7563                 t->backgroundglowtexture = NULL;
7564         }
7565         t->specularpower = r_shadow_glossexponent.value;
7566         // TODO: store reference values for these in the texture?
7567         t->specularscale = 0;
7568         if (r_shadow_gloss.integer > 0)
7569         {
7570                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7571                 {
7572                         if (r_shadow_glossintensity.value > 0)
7573                         {
7574                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7575                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7576                                 t->specularscale = r_shadow_glossintensity.value;
7577                         }
7578                 }
7579                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7580                 {
7581                         t->glosstexture = r_texture_white;
7582                         t->backgroundglosstexture = r_texture_white;
7583                         t->specularscale = r_shadow_gloss2intensity.value;
7584                         t->specularpower = r_shadow_gloss2exponent.value;
7585                 }
7586         }
7587         t->specularscale *= t->specularscalemod;
7588         t->specularpower *= t->specularpowermod;
7589
7590         // lightmaps mode looks bad with dlights using actual texturing, so turn
7591         // off the colormap and glossmap, but leave the normalmap on as it still
7592         // accurately represents the shading involved
7593         if (gl_lightmaps.integer)
7594         {
7595                 t->basetexture = r_texture_grey128;
7596                 t->pantstexture = r_texture_black;
7597                 t->shirttexture = r_texture_black;
7598                 t->nmaptexture = r_texture_blanknormalmap;
7599                 t->glosstexture = r_texture_black;
7600                 t->glowtexture = NULL;
7601                 t->fogtexture = NULL;
7602                 t->reflectmasktexture = NULL;
7603                 t->backgroundbasetexture = NULL;
7604                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7605                 t->backgroundglosstexture = r_texture_black;
7606                 t->backgroundglowtexture = NULL;
7607                 t->specularscale = 0;
7608                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7609         }
7610
7611         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7612         VectorClear(t->dlightcolor);
7613         t->currentnumlayers = 0;
7614         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7615         {
7616                 int blendfunc1, blendfunc2;
7617                 qboolean depthmask;
7618                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7619                 {
7620                         blendfunc1 = GL_SRC_ALPHA;
7621                         blendfunc2 = GL_ONE;
7622                 }
7623                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7624                 {
7625                         blendfunc1 = GL_SRC_ALPHA;
7626                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7627                 }
7628                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7629                 {
7630                         blendfunc1 = t->customblendfunc[0];
7631                         blendfunc2 = t->customblendfunc[1];
7632                 }
7633                 else
7634                 {
7635                         blendfunc1 = GL_ONE;
7636                         blendfunc2 = GL_ZERO;
7637                 }
7638                 // don't colormod evilblend textures
7639                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7640                         VectorSet(t->lightmapcolor, 1, 1, 1);
7641                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7642                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7643                 {
7644                         // fullbright is not affected by r_refdef.lightmapintensity
7645                         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]);
7646                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7647                                 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]);
7648                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7649                                 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]);
7650                 }
7651                 else
7652                 {
7653                         vec3_t ambientcolor;
7654                         float colorscale;
7655                         // set the color tint used for lights affecting this surface
7656                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7657                         colorscale = 2;
7658                         // q3bsp has no lightmap updates, so the lightstylevalue that
7659                         // would normally be baked into the lightmap must be
7660                         // applied to the color
7661                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7662                         if (model->type == mod_brushq3)
7663                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7664                         colorscale *= r_refdef.lightmapintensity;
7665                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7666                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7667                         // basic lit geometry
7668                         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]);
7669                         // add pants/shirt if needed
7670                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7671                                 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]);
7672                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7673                                 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]);
7674                         // now add ambient passes if needed
7675                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7676                         {
7677                                 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]);
7678                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7679                                         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]);
7680                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7681                                         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]);
7682                         }
7683                 }
7684                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7685                         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]);
7686                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7687                 {
7688                         // if this is opaque use alpha blend which will darken the earlier
7689                         // passes cheaply.
7690                         //
7691                         // if this is an alpha blended material, all the earlier passes
7692                         // were darkened by fog already, so we only need to add the fog
7693                         // color ontop through the fog mask texture
7694                         //
7695                         // if this is an additive blended material, all the earlier passes
7696                         // were darkened by fog already, and we should not add fog color
7697                         // (because the background was not darkened, there is no fog color
7698                         // that was lost behind it).
7699                         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]);
7700                 }
7701         }
7702
7703         return t->currentframe;
7704 }
7705
7706 rsurfacestate_t rsurface;
7707
7708 void RSurf_ActiveWorldEntity(void)
7709 {
7710         dp_model_t *model = r_refdef.scene.worldmodel;
7711         //if (rsurface.entity == r_refdef.scene.worldentity)
7712         //      return;
7713         rsurface.entity = r_refdef.scene.worldentity;
7714         rsurface.skeleton = NULL;
7715         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7716         rsurface.ent_skinnum = 0;
7717         rsurface.ent_qwskin = -1;
7718         rsurface.ent_shadertime = 0;
7719         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7720         rsurface.matrix = identitymatrix;
7721         rsurface.inversematrix = identitymatrix;
7722         rsurface.matrixscale = 1;
7723         rsurface.inversematrixscale = 1;
7724         R_EntityMatrix(&identitymatrix);
7725         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7726         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7727         rsurface.fograngerecip = r_refdef.fograngerecip;
7728         rsurface.fogheightfade = r_refdef.fogheightfade;
7729         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7730         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7731         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7732         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7733         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7734         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7735         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7736         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7737         rsurface.colormod[3] = 1;
7738         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);
7739         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7740         rsurface.frameblend[0].lerp = 1;
7741         rsurface.ent_alttextures = false;
7742         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7743         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7744         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7745         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7746         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7747         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7748         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7749         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7750         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7751         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7752         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7753         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7754         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7755         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7756         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7757         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7758         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7759         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7760         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7761         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7762         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7763         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7765         rsurface.modelelement3i = model->surfmesh.data_element3i;
7766         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7767         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7768         rsurface.modelelement3s = model->surfmesh.data_element3s;
7769         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7770         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7771         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7772         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7773         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7774         rsurface.modelsurfaces = model->data_surfaces;
7775         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7776         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7777         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7778         rsurface.modelgeneratedvertex = false;
7779         rsurface.batchgeneratedvertex = false;
7780         rsurface.batchfirstvertex = 0;
7781         rsurface.batchnumvertices = 0;
7782         rsurface.batchfirsttriangle = 0;
7783         rsurface.batchnumtriangles = 0;
7784         rsurface.batchvertex3f  = NULL;
7785         rsurface.batchvertex3f_vertexbuffer = NULL;
7786         rsurface.batchvertex3f_bufferoffset = 0;
7787         rsurface.batchsvector3f = NULL;
7788         rsurface.batchsvector3f_vertexbuffer = NULL;
7789         rsurface.batchsvector3f_bufferoffset = 0;
7790         rsurface.batchtvector3f = NULL;
7791         rsurface.batchtvector3f_vertexbuffer = NULL;
7792         rsurface.batchtvector3f_bufferoffset = 0;
7793         rsurface.batchnormal3f  = NULL;
7794         rsurface.batchnormal3f_vertexbuffer = NULL;
7795         rsurface.batchnormal3f_bufferoffset = 0;
7796         rsurface.batchlightmapcolor4f = NULL;
7797         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7798         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7799         rsurface.batchtexcoordtexture2f = NULL;
7800         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7801         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7802         rsurface.batchtexcoordlightmap2f = NULL;
7803         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7804         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7805         rsurface.batchvertexmesh = NULL;
7806         rsurface.batchvertexmeshbuffer = NULL;
7807         rsurface.batchvertex3fbuffer = NULL;
7808         rsurface.batchelement3i = NULL;
7809         rsurface.batchelement3i_indexbuffer = NULL;
7810         rsurface.batchelement3i_bufferoffset = 0;
7811         rsurface.batchelement3s = NULL;
7812         rsurface.batchelement3s_indexbuffer = NULL;
7813         rsurface.batchelement3s_bufferoffset = 0;
7814         rsurface.passcolor4f = NULL;
7815         rsurface.passcolor4f_vertexbuffer = NULL;
7816         rsurface.passcolor4f_bufferoffset = 0;
7817 }
7818
7819 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7820 {
7821         dp_model_t *model = ent->model;
7822         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7823         //      return;
7824         rsurface.entity = (entity_render_t *)ent;
7825         rsurface.skeleton = ent->skeleton;
7826         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7827         rsurface.ent_skinnum = ent->skinnum;
7828         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;
7829         rsurface.ent_shadertime = ent->shadertime;
7830         rsurface.ent_flags = ent->flags;
7831         rsurface.matrix = ent->matrix;
7832         rsurface.inversematrix = ent->inversematrix;
7833         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7834         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7835         R_EntityMatrix(&rsurface.matrix);
7836         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7837         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7838         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7839         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7840         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7841         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7842         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7843         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7844         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7845         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7846         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7847         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7848         rsurface.colormod[3] = ent->alpha;
7849         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7850         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7851         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7852         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7853         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7854         if (ent->model->brush.submodel && !prepass)
7855         {
7856                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7857                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7858         }
7859         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7860         {
7861                 if (ent->animcache_vertex3f)
7862                 {
7863                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7864                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7865                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7866                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7867                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7868                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7869                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7870                 }
7871                 else if (wanttangents)
7872                 {
7873                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7874                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7875                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7876                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7877                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7878                         rsurface.modelvertexmesh = NULL;
7879                         rsurface.modelvertexmeshbuffer = NULL;
7880                         rsurface.modelvertex3fbuffer = NULL;
7881                 }
7882                 else if (wantnormals)
7883                 {
7884                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7885                         rsurface.modelsvector3f = NULL;
7886                         rsurface.modeltvector3f = NULL;
7887                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7888                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7889                         rsurface.modelvertexmesh = NULL;
7890                         rsurface.modelvertexmeshbuffer = NULL;
7891                         rsurface.modelvertex3fbuffer = NULL;
7892                 }
7893                 else
7894                 {
7895                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7896                         rsurface.modelsvector3f = NULL;
7897                         rsurface.modeltvector3f = NULL;
7898                         rsurface.modelnormal3f = NULL;
7899                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7900                         rsurface.modelvertexmesh = NULL;
7901                         rsurface.modelvertexmeshbuffer = NULL;
7902                         rsurface.modelvertex3fbuffer = NULL;
7903                 }
7904                 rsurface.modelvertex3f_vertexbuffer = 0;
7905                 rsurface.modelvertex3f_bufferoffset = 0;
7906                 rsurface.modelsvector3f_vertexbuffer = 0;
7907                 rsurface.modelsvector3f_bufferoffset = 0;
7908                 rsurface.modeltvector3f_vertexbuffer = 0;
7909                 rsurface.modeltvector3f_bufferoffset = 0;
7910                 rsurface.modelnormal3f_vertexbuffer = 0;
7911                 rsurface.modelnormal3f_bufferoffset = 0;
7912                 rsurface.modelgeneratedvertex = true;
7913         }
7914         else
7915         {
7916                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7917                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7918                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7919                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7920                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7921                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7922                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7923                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7924                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7925                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7926                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7927                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7928                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7929                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7930                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7931                 rsurface.modelgeneratedvertex = false;
7932         }
7933         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7934         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7935         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7936         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7937         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7938         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7939         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7940         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7941         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7942         rsurface.modelelement3i = model->surfmesh.data_element3i;
7943         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7944         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7945         rsurface.modelelement3s = model->surfmesh.data_element3s;
7946         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7947         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7948         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7949         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7950         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7951         rsurface.modelsurfaces = model->data_surfaces;
7952         rsurface.batchgeneratedvertex = false;
7953         rsurface.batchfirstvertex = 0;
7954         rsurface.batchnumvertices = 0;
7955         rsurface.batchfirsttriangle = 0;
7956         rsurface.batchnumtriangles = 0;
7957         rsurface.batchvertex3f  = NULL;
7958         rsurface.batchvertex3f_vertexbuffer = NULL;
7959         rsurface.batchvertex3f_bufferoffset = 0;
7960         rsurface.batchsvector3f = NULL;
7961         rsurface.batchsvector3f_vertexbuffer = NULL;
7962         rsurface.batchsvector3f_bufferoffset = 0;
7963         rsurface.batchtvector3f = NULL;
7964         rsurface.batchtvector3f_vertexbuffer = NULL;
7965         rsurface.batchtvector3f_bufferoffset = 0;
7966         rsurface.batchnormal3f  = NULL;
7967         rsurface.batchnormal3f_vertexbuffer = NULL;
7968         rsurface.batchnormal3f_bufferoffset = 0;
7969         rsurface.batchlightmapcolor4f = NULL;
7970         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7971         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7972         rsurface.batchtexcoordtexture2f = NULL;
7973         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7974         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7975         rsurface.batchtexcoordlightmap2f = NULL;
7976         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7977         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7978         rsurface.batchvertexmesh = NULL;
7979         rsurface.batchvertexmeshbuffer = NULL;
7980         rsurface.batchvertex3fbuffer = NULL;
7981         rsurface.batchelement3i = NULL;
7982         rsurface.batchelement3i_indexbuffer = NULL;
7983         rsurface.batchelement3i_bufferoffset = 0;
7984         rsurface.batchelement3s = NULL;
7985         rsurface.batchelement3s_indexbuffer = NULL;
7986         rsurface.batchelement3s_bufferoffset = 0;
7987         rsurface.passcolor4f = NULL;
7988         rsurface.passcolor4f_vertexbuffer = NULL;
7989         rsurface.passcolor4f_bufferoffset = 0;
7990 }
7991
7992 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)
7993 {
7994         rsurface.entity = r_refdef.scene.worldentity;
7995         rsurface.skeleton = NULL;
7996         rsurface.ent_skinnum = 0;
7997         rsurface.ent_qwskin = -1;
7998         rsurface.ent_shadertime = shadertime;
7999         rsurface.ent_flags = entflags;
8000         rsurface.modelnumvertices = numvertices;
8001         rsurface.modelnumtriangles = numtriangles;
8002         rsurface.matrix = *matrix;
8003         rsurface.inversematrix = *inversematrix;
8004         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8005         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8006         R_EntityMatrix(&rsurface.matrix);
8007         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8008         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8009         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8010         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8011         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8012         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8013         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8014         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8015         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8016         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8017         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8018         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8019         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);
8020         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8021         rsurface.frameblend[0].lerp = 1;
8022         rsurface.ent_alttextures = false;
8023         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8024         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8025         if (wanttangents)
8026         {
8027                 rsurface.modelvertex3f = (float *)vertex3f;
8028                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8029                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8030                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8031         }
8032         else if (wantnormals)
8033         {
8034                 rsurface.modelvertex3f = (float *)vertex3f;
8035                 rsurface.modelsvector3f = NULL;
8036                 rsurface.modeltvector3f = NULL;
8037                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8038         }
8039         else
8040         {
8041                 rsurface.modelvertex3f = (float *)vertex3f;
8042                 rsurface.modelsvector3f = NULL;
8043                 rsurface.modeltvector3f = NULL;
8044                 rsurface.modelnormal3f = NULL;
8045         }
8046         rsurface.modelvertexmesh = NULL;
8047         rsurface.modelvertexmeshbuffer = NULL;
8048         rsurface.modelvertex3fbuffer = NULL;
8049         rsurface.modelvertex3f_vertexbuffer = 0;
8050         rsurface.modelvertex3f_bufferoffset = 0;
8051         rsurface.modelsvector3f_vertexbuffer = 0;
8052         rsurface.modelsvector3f_bufferoffset = 0;
8053         rsurface.modeltvector3f_vertexbuffer = 0;
8054         rsurface.modeltvector3f_bufferoffset = 0;
8055         rsurface.modelnormal3f_vertexbuffer = 0;
8056         rsurface.modelnormal3f_bufferoffset = 0;
8057         rsurface.modelgeneratedvertex = true;
8058         rsurface.modellightmapcolor4f  = (float *)color4f;
8059         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8060         rsurface.modellightmapcolor4f_bufferoffset = 0;
8061         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8062         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8063         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8064         rsurface.modeltexcoordlightmap2f  = NULL;
8065         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8066         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8067         rsurface.modelelement3i = (int *)element3i;
8068         rsurface.modelelement3i_indexbuffer = NULL;
8069         rsurface.modelelement3i_bufferoffset = 0;
8070         rsurface.modelelement3s = (unsigned short *)element3s;
8071         rsurface.modelelement3s_indexbuffer = NULL;
8072         rsurface.modelelement3s_bufferoffset = 0;
8073         rsurface.modellightmapoffsets = NULL;
8074         rsurface.modelsurfaces = NULL;
8075         rsurface.batchgeneratedvertex = false;
8076         rsurface.batchfirstvertex = 0;
8077         rsurface.batchnumvertices = 0;
8078         rsurface.batchfirsttriangle = 0;
8079         rsurface.batchnumtriangles = 0;
8080         rsurface.batchvertex3f  = NULL;
8081         rsurface.batchvertex3f_vertexbuffer = NULL;
8082         rsurface.batchvertex3f_bufferoffset = 0;
8083         rsurface.batchsvector3f = NULL;
8084         rsurface.batchsvector3f_vertexbuffer = NULL;
8085         rsurface.batchsvector3f_bufferoffset = 0;
8086         rsurface.batchtvector3f = NULL;
8087         rsurface.batchtvector3f_vertexbuffer = NULL;
8088         rsurface.batchtvector3f_bufferoffset = 0;
8089         rsurface.batchnormal3f  = NULL;
8090         rsurface.batchnormal3f_vertexbuffer = NULL;
8091         rsurface.batchnormal3f_bufferoffset = 0;
8092         rsurface.batchlightmapcolor4f = NULL;
8093         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8094         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8095         rsurface.batchtexcoordtexture2f = NULL;
8096         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8097         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8098         rsurface.batchtexcoordlightmap2f = NULL;
8099         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8100         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8101         rsurface.batchvertexmesh = NULL;
8102         rsurface.batchvertexmeshbuffer = NULL;
8103         rsurface.batchvertex3fbuffer = NULL;
8104         rsurface.batchelement3i = NULL;
8105         rsurface.batchelement3i_indexbuffer = NULL;
8106         rsurface.batchelement3i_bufferoffset = 0;
8107         rsurface.batchelement3s = NULL;
8108         rsurface.batchelement3s_indexbuffer = NULL;
8109         rsurface.batchelement3s_bufferoffset = 0;
8110         rsurface.passcolor4f = NULL;
8111         rsurface.passcolor4f_vertexbuffer = NULL;
8112         rsurface.passcolor4f_bufferoffset = 0;
8113
8114         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8115         {
8116                 if ((wantnormals || wanttangents) && !normal3f)
8117                 {
8118                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8119                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8120                 }
8121                 if (wanttangents && !svector3f)
8122                 {
8123                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8124                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8125                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8126                 }
8127         }
8128 }
8129
8130 float RSurf_FogPoint(const float *v)
8131 {
8132         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8133         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8134         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8135         float FogHeightFade = r_refdef.fogheightfade;
8136         float fogfrac;
8137         unsigned int fogmasktableindex;
8138         if (r_refdef.fogplaneviewabove)
8139                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8140         else
8141                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8142         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8143         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8144 }
8145
8146 float RSurf_FogVertex(const float *v)
8147 {
8148         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8149         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8150         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8151         float FogHeightFade = rsurface.fogheightfade;
8152         float fogfrac;
8153         unsigned int fogmasktableindex;
8154         if (r_refdef.fogplaneviewabove)
8155                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8156         else
8157                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8158         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8159         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8160 }
8161
8162 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8163 {
8164         int i;
8165         for (i = 0;i < numelements;i++)
8166                 outelement3i[i] = inelement3i[i] + adjust;
8167 }
8168
8169 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8170 extern cvar_t gl_vbo;
8171 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8172 {
8173         int deformindex;
8174         int firsttriangle;
8175         int numtriangles;
8176         int firstvertex;
8177         int endvertex;
8178         int numvertices;
8179         int surfacefirsttriangle;
8180         int surfacenumtriangles;
8181         int surfacefirstvertex;
8182         int surfaceendvertex;
8183         int surfacenumvertices;
8184         int batchnumvertices;
8185         int batchnumtriangles;
8186         int needsupdate;
8187         int i, j;
8188         qboolean gaps;
8189         qboolean dynamicvertex;
8190         float amplitude;
8191         float animpos;
8192         float scale;
8193         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8194         float waveparms[4];
8195         q3shaderinfo_deform_t *deform;
8196         const msurface_t *surface, *firstsurface;
8197         r_vertexmesh_t *vertexmesh;
8198         if (!texturenumsurfaces)
8199                 return;
8200         // find vertex range of this surface batch
8201         gaps = false;
8202         firstsurface = texturesurfacelist[0];
8203         firsttriangle = firstsurface->num_firsttriangle;
8204         batchnumvertices = 0;
8205         batchnumtriangles = 0;
8206         firstvertex = endvertex = firstsurface->num_firstvertex;
8207         for (i = 0;i < texturenumsurfaces;i++)
8208         {
8209                 surface = texturesurfacelist[i];
8210                 if (surface != firstsurface + i)
8211                         gaps = true;
8212                 surfacefirstvertex = surface->num_firstvertex;
8213                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8214                 surfacenumvertices = surface->num_vertices;
8215                 surfacenumtriangles = surface->num_triangles;
8216                 if (firstvertex > surfacefirstvertex)
8217                         firstvertex = surfacefirstvertex;
8218                 if (endvertex < surfaceendvertex)
8219                         endvertex = surfaceendvertex;
8220                 batchnumvertices += surfacenumvertices;
8221                 batchnumtriangles += surfacenumtriangles;
8222         }
8223
8224         // we now know the vertex range used, and if there are any gaps in it
8225         rsurface.batchfirstvertex = firstvertex;
8226         rsurface.batchnumvertices = endvertex - firstvertex;
8227         rsurface.batchfirsttriangle = firsttriangle;
8228         rsurface.batchnumtriangles = batchnumtriangles;
8229
8230         // this variable holds flags for which properties have been updated that
8231         // may require regenerating vertexmesh array...
8232         needsupdate = 0;
8233
8234         // check if any dynamic vertex processing must occur
8235         dynamicvertex = false;
8236
8237         // if there is a chance of animated vertex colors, it's a dynamic batch
8238         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8239         {
8240                 dynamicvertex = true;
8241                 batchneed |= BATCHNEED_NOGAPS;
8242                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8243         }
8244
8245         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8246         {
8247                 switch (deform->deform)
8248                 {
8249                 default:
8250                 case Q3DEFORM_PROJECTIONSHADOW:
8251                 case Q3DEFORM_TEXT0:
8252                 case Q3DEFORM_TEXT1:
8253                 case Q3DEFORM_TEXT2:
8254                 case Q3DEFORM_TEXT3:
8255                 case Q3DEFORM_TEXT4:
8256                 case Q3DEFORM_TEXT5:
8257                 case Q3DEFORM_TEXT6:
8258                 case Q3DEFORM_TEXT7:
8259                 case Q3DEFORM_NONE:
8260                         break;
8261                 case Q3DEFORM_AUTOSPRITE:
8262                         dynamicvertex = true;
8263                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8264                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8265                         break;
8266                 case Q3DEFORM_AUTOSPRITE2:
8267                         dynamicvertex = true;
8268                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8269                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8270                         break;
8271                 case Q3DEFORM_NORMAL:
8272                         dynamicvertex = true;
8273                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8274                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8275                         break;
8276                 case Q3DEFORM_WAVE:
8277                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8278                                 break; // if wavefunc is a nop, ignore this transform
8279                         dynamicvertex = true;
8280                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8281                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8282                         break;
8283                 case Q3DEFORM_BULGE:
8284                         dynamicvertex = true;
8285                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8286                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8287                         break;
8288                 case Q3DEFORM_MOVE:
8289                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8290                                 break; // if wavefunc is a nop, ignore this transform
8291                         dynamicvertex = true;
8292                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8293                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8294                         break;
8295                 }
8296         }
8297         switch(rsurface.texture->tcgen.tcgen)
8298         {
8299         default:
8300         case Q3TCGEN_TEXTURE:
8301                 break;
8302         case Q3TCGEN_LIGHTMAP:
8303                 dynamicvertex = true;
8304                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8305                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8306                 break;
8307         case Q3TCGEN_VECTOR:
8308                 dynamicvertex = true;
8309                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8310                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8311                 break;
8312         case Q3TCGEN_ENVIRONMENT:
8313                 dynamicvertex = true;
8314                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8315                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8316                 break;
8317         }
8318         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8319         {
8320                 dynamicvertex = true;
8321                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8322                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8323         }
8324
8325         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8326         {
8327                 dynamicvertex = true;
8328                 batchneed |= BATCHNEED_NOGAPS;
8329                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8330         }
8331
8332         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8333         {
8334                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8335                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8336                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8337                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8338                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8339                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8340                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8341         }
8342
8343         // when the model data has no vertex buffer (dynamic mesh), we need to
8344         // eliminate gaps
8345         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8346                 batchneed |= BATCHNEED_NOGAPS;
8347
8348         // if needsupdate, we have to do a dynamic vertex batch for sure
8349         if (needsupdate & batchneed)
8350                 dynamicvertex = true;
8351
8352         // see if we need to build vertexmesh from arrays
8353         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8354                 dynamicvertex = true;
8355
8356         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8357         // also some drivers strongly dislike firstvertex
8358         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8359                 dynamicvertex = true;
8360
8361         rsurface.batchvertex3f = rsurface.modelvertex3f;
8362         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8363         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8364         rsurface.batchsvector3f = rsurface.modelsvector3f;
8365         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8366         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8367         rsurface.batchtvector3f = rsurface.modeltvector3f;
8368         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8369         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8370         rsurface.batchnormal3f = rsurface.modelnormal3f;
8371         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8372         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8373         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8374         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8375         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8376         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8377         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8378         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8379         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8380         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8381         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8382         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8383         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8384         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8385         rsurface.batchelement3i = rsurface.modelelement3i;
8386         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8387         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8388         rsurface.batchelement3s = rsurface.modelelement3s;
8389         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8390         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8391
8392         // if any dynamic vertex processing has to occur in software, we copy the
8393         // entire surface list together before processing to rebase the vertices
8394         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8395         //
8396         // if any gaps exist and we do not have a static vertex buffer, we have to
8397         // copy the surface list together to avoid wasting upload bandwidth on the
8398         // vertices in the gaps.
8399         //
8400         // if gaps exist and we have a static vertex buffer, we still have to
8401         // combine the index buffer ranges into one dynamic index buffer.
8402         //
8403         // in all cases we end up with data that can be drawn in one call.
8404
8405         if (!dynamicvertex)
8406         {
8407                 // static vertex data, just set pointers...
8408                 rsurface.batchgeneratedvertex = false;
8409                 // if there are gaps, we want to build a combined index buffer,
8410                 // otherwise use the original static buffer with an appropriate offset
8411                 if (gaps)
8412                 {
8413                         // build a new triangle elements array for this batch
8414                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8415                         rsurface.batchfirsttriangle = 0;
8416                         numtriangles = 0;
8417                         for (i = 0;i < texturenumsurfaces;i++)
8418                         {
8419                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8420                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8421                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8422                                 numtriangles += surfacenumtriangles;
8423                         }
8424                         rsurface.batchelement3i_indexbuffer = NULL;
8425                         rsurface.batchelement3i_bufferoffset = 0;
8426                         rsurface.batchelement3s = NULL;
8427                         rsurface.batchelement3s_indexbuffer = NULL;
8428                         rsurface.batchelement3s_bufferoffset = 0;
8429                         if (endvertex <= 65536)
8430                         {
8431                                 // make a 16bit (unsigned short) index array if possible
8432                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8433                                 for (i = 0;i < numtriangles*3;i++)
8434                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8435                         }
8436                 }
8437                 return;
8438         }
8439
8440         // something needs software processing, do it for real...
8441         // we only directly handle separate array data in this case and then
8442         // generate interleaved data if needed...
8443         rsurface.batchgeneratedvertex = true;
8444
8445         // now copy the vertex data into a combined array and make an index array
8446         // (this is what Quake3 does all the time)
8447         //if (gaps || rsurface.batchfirstvertex)
8448         {
8449                 rsurface.batchvertex3fbuffer = NULL;
8450                 rsurface.batchvertexmesh = NULL;
8451                 rsurface.batchvertexmeshbuffer = NULL;
8452                 rsurface.batchvertex3f = NULL;
8453                 rsurface.batchvertex3f_vertexbuffer = NULL;
8454                 rsurface.batchvertex3f_bufferoffset = 0;
8455                 rsurface.batchsvector3f = NULL;
8456                 rsurface.batchsvector3f_vertexbuffer = NULL;
8457                 rsurface.batchsvector3f_bufferoffset = 0;
8458                 rsurface.batchtvector3f = NULL;
8459                 rsurface.batchtvector3f_vertexbuffer = NULL;
8460                 rsurface.batchtvector3f_bufferoffset = 0;
8461                 rsurface.batchnormal3f = NULL;
8462                 rsurface.batchnormal3f_vertexbuffer = NULL;
8463                 rsurface.batchnormal3f_bufferoffset = 0;
8464                 rsurface.batchlightmapcolor4f = NULL;
8465                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8466                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8467                 rsurface.batchtexcoordtexture2f = NULL;
8468                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8469                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8470                 rsurface.batchtexcoordlightmap2f = NULL;
8471                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8472                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8473                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8474                 rsurface.batchelement3i_indexbuffer = NULL;
8475                 rsurface.batchelement3i_bufferoffset = 0;
8476                 rsurface.batchelement3s = NULL;
8477                 rsurface.batchelement3s_indexbuffer = NULL;
8478                 rsurface.batchelement3s_bufferoffset = 0;
8479                 // we'll only be setting up certain arrays as needed
8480                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8481                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8482                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8483                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8484                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8485                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8486                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8487                 {
8488                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8489                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8490                 }
8491                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8492                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8493                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8494                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8495                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8496                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8497                 numvertices = 0;
8498                 numtriangles = 0;
8499                 for (i = 0;i < texturenumsurfaces;i++)
8500                 {
8501                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8502                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8503                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8504                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8505                         // copy only the data requested
8506                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8507                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8508                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8509                         {
8510                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8511                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8512                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8513                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8514                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8515                                 {
8516                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8517                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8518                                 }
8519                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8520                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8521                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8522                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8523                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8524                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8525                         }
8526                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8527                         numvertices += surfacenumvertices;
8528                         numtriangles += surfacenumtriangles;
8529                 }
8530
8531                 // generate a 16bit index array as well if possible
8532                 // (in general, dynamic batches fit)
8533                 if (numvertices <= 65536)
8534                 {
8535                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8536                         for (i = 0;i < numtriangles*3;i++)
8537                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8538                 }
8539
8540                 // since we've copied everything, the batch now starts at 0
8541                 rsurface.batchfirstvertex = 0;
8542                 rsurface.batchnumvertices = batchnumvertices;
8543                 rsurface.batchfirsttriangle = 0;
8544                 rsurface.batchnumtriangles = batchnumtriangles;
8545         }
8546
8547         // q1bsp surfaces rendered in vertex color mode have to have colors
8548         // calculated based on lightstyles
8549         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8550         {
8551                 // generate color arrays for the surfaces in this list
8552                 int c[4];
8553                 int scale;
8554                 int size3;
8555                 const int *offsets;
8556                 const unsigned char *lm;
8557                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8558                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8559                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8560                 numvertices = 0;
8561                 for (i = 0;i < texturenumsurfaces;i++)
8562                 {
8563                         surface = texturesurfacelist[i];
8564                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8565                         surfacenumvertices = surface->num_vertices;
8566                         if (surface->lightmapinfo->samples)
8567                         {
8568                                 for (j = 0;j < surfacenumvertices;j++)
8569                                 {
8570                                         lm = surface->lightmapinfo->samples + offsets[j];
8571                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8572                                         VectorScale(lm, scale, c);
8573                                         if (surface->lightmapinfo->styles[1] != 255)
8574                                         {
8575                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8576                                                 lm += size3;
8577                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8578                                                 VectorMA(c, scale, lm, c);
8579                                                 if (surface->lightmapinfo->styles[2] != 255)
8580                                                 {
8581                                                         lm += size3;
8582                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8583                                                         VectorMA(c, scale, lm, c);
8584                                                         if (surface->lightmapinfo->styles[3] != 255)
8585                                                         {
8586                                                                 lm += size3;
8587                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8588                                                                 VectorMA(c, scale, lm, c);
8589                                                         }
8590                                                 }
8591                                         }
8592                                         c[0] >>= 7;
8593                                         c[1] >>= 7;
8594                                         c[2] >>= 7;
8595                                         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);
8596                                         numvertices++;
8597                                 }
8598                         }
8599                         else
8600                         {
8601                                 for (j = 0;j < surfacenumvertices;j++)
8602                                 {
8603                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8604                                         numvertices++;
8605                                 }
8606                         }
8607                 }
8608         }
8609
8610         // if vertices are deformed (sprite flares and things in maps, possibly
8611         // water waves, bulges and other deformations), modify the copied vertices
8612         // in place
8613         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8614         {
8615                 switch (deform->deform)
8616                 {
8617                 default:
8618                 case Q3DEFORM_PROJECTIONSHADOW:
8619                 case Q3DEFORM_TEXT0:
8620                 case Q3DEFORM_TEXT1:
8621                 case Q3DEFORM_TEXT2:
8622                 case Q3DEFORM_TEXT3:
8623                 case Q3DEFORM_TEXT4:
8624                 case Q3DEFORM_TEXT5:
8625                 case Q3DEFORM_TEXT6:
8626                 case Q3DEFORM_TEXT7:
8627                 case Q3DEFORM_NONE:
8628                         break;
8629                 case Q3DEFORM_AUTOSPRITE:
8630                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8631                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8632                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8633                         VectorNormalize(newforward);
8634                         VectorNormalize(newright);
8635                         VectorNormalize(newup);
8636 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8637 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8638 //                      rsurface.batchvertex3f_bufferoffset = 0;
8639 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8640 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8641 //                      rsurface.batchsvector3f_bufferoffset = 0;
8642 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8643 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8644 //                      rsurface.batchtvector3f_bufferoffset = 0;
8645 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8646 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8647 //                      rsurface.batchnormal3f_bufferoffset = 0;
8648                         // a single autosprite surface can contain multiple sprites...
8649                         for (j = 0;j < batchnumvertices - 3;j += 4)
8650                         {
8651                                 VectorClear(center);
8652                                 for (i = 0;i < 4;i++)
8653                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8654                                 VectorScale(center, 0.25f, center);
8655                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8656                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8657                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8658                                 for (i = 0;i < 4;i++)
8659                                 {
8660                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8661                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8662                                 }
8663                         }
8664                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8665                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8666                         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);
8667                         break;
8668                 case Q3DEFORM_AUTOSPRITE2:
8669                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8670                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8671                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8672                         VectorNormalize(newforward);
8673                         VectorNormalize(newright);
8674                         VectorNormalize(newup);
8675 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8676 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8677 //                      rsurface.batchvertex3f_bufferoffset = 0;
8678                         {
8679                                 const float *v1, *v2;
8680                                 vec3_t start, end;
8681                                 float f, l;
8682                                 struct
8683                                 {
8684                                         float length2;
8685                                         const float *v1;
8686                                         const float *v2;
8687                                 }
8688                                 shortest[2];
8689                                 memset(shortest, 0, sizeof(shortest));
8690                                 // a single autosprite surface can contain multiple sprites...
8691                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8692                                 {
8693                                         VectorClear(center);
8694                                         for (i = 0;i < 4;i++)
8695                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8696                                         VectorScale(center, 0.25f, center);
8697                                         // find the two shortest edges, then use them to define the
8698                                         // axis vectors for rotating around the central axis
8699                                         for (i = 0;i < 6;i++)
8700                                         {
8701                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8702                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8703                                                 l = VectorDistance2(v1, v2);
8704                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8705                                                 if (v1[2] != v2[2])
8706                                                         l += (1.0f / 1024.0f);
8707                                                 if (shortest[0].length2 > l || i == 0)
8708                                                 {
8709                                                         shortest[1] = shortest[0];
8710                                                         shortest[0].length2 = l;
8711                                                         shortest[0].v1 = v1;
8712                                                         shortest[0].v2 = v2;
8713                                                 }
8714                                                 else if (shortest[1].length2 > l || i == 1)
8715                                                 {
8716                                                         shortest[1].length2 = l;
8717                                                         shortest[1].v1 = v1;
8718                                                         shortest[1].v2 = v2;
8719                                                 }
8720                                         }
8721                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8722                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8723                                         // this calculates the right vector from the shortest edge
8724                                         // and the up vector from the edge midpoints
8725                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8726                                         VectorNormalize(right);
8727                                         VectorSubtract(end, start, up);
8728                                         VectorNormalize(up);
8729                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8730                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8731                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8732                                         VectorNegate(forward, forward);
8733                                         VectorReflect(forward, 0, up, forward);
8734                                         VectorNormalize(forward);
8735                                         CrossProduct(up, forward, newright);
8736                                         VectorNormalize(newright);
8737                                         // rotate the quad around the up axis vector, this is made
8738                                         // especially easy by the fact we know the quad is flat,
8739                                         // so we only have to subtract the center position and
8740                                         // measure distance along the right vector, and then
8741                                         // multiply that by the newright vector and add back the
8742                                         // center position
8743                                         // we also need to subtract the old position to undo the
8744                                         // displacement from the center, which we do with a
8745                                         // DotProduct, the subtraction/addition of center is also
8746                                         // optimized into DotProducts here
8747                                         l = DotProduct(right, center);
8748                                         for (i = 0;i < 4;i++)
8749                                         {
8750                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8751                                                 f = DotProduct(right, v1) - l;
8752                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8753                                         }
8754                                 }
8755                         }
8756                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8757                         {
8758 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8759 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8760 //                              rsurface.batchnormal3f_bufferoffset = 0;
8761                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8762                         }
8763                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8764                         {
8765 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8766 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8767 //                              rsurface.batchsvector3f_bufferoffset = 0;
8768 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8769 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8770 //                              rsurface.batchtvector3f_bufferoffset = 0;
8771                                 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);
8772                         }
8773                         break;
8774                 case Q3DEFORM_NORMAL:
8775                         // deform the normals to make reflections wavey
8776                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8777                         rsurface.batchnormal3f_vertexbuffer = NULL;
8778                         rsurface.batchnormal3f_bufferoffset = 0;
8779                         for (j = 0;j < batchnumvertices;j++)
8780                         {
8781                                 float vertex[3];
8782                                 float *normal = rsurface.batchnormal3f + 3*j;
8783                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8784                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8785                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8786                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8787                                 VectorNormalize(normal);
8788                         }
8789                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8790                         {
8791 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8792 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8793 //                              rsurface.batchsvector3f_bufferoffset = 0;
8794 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8795 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8796 //                              rsurface.batchtvector3f_bufferoffset = 0;
8797                                 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);
8798                         }
8799                         break;
8800                 case Q3DEFORM_WAVE:
8801                         // deform vertex array to make wavey water and flags and such
8802                         waveparms[0] = deform->waveparms[0];
8803                         waveparms[1] = deform->waveparms[1];
8804                         waveparms[2] = deform->waveparms[2];
8805                         waveparms[3] = deform->waveparms[3];
8806                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8807                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8808                         // this is how a divisor of vertex influence on deformation
8809                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8810                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8811 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8812 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8813 //                      rsurface.batchvertex3f_bufferoffset = 0;
8814 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8815 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8816 //                      rsurface.batchnormal3f_bufferoffset = 0;
8817                         for (j = 0;j < batchnumvertices;j++)
8818                         {
8819                                 // if the wavefunc depends on time, evaluate it per-vertex
8820                                 if (waveparms[3])
8821                                 {
8822                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8823                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8824                                 }
8825                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8826                         }
8827                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8828                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8829                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8830                         {
8831 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8832 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8833 //                              rsurface.batchsvector3f_bufferoffset = 0;
8834 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8835 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8836 //                              rsurface.batchtvector3f_bufferoffset = 0;
8837                                 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);
8838                         }
8839                         break;
8840                 case Q3DEFORM_BULGE:
8841                         // deform vertex array to make the surface have moving bulges
8842 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8843 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8844 //                      rsurface.batchvertex3f_bufferoffset = 0;
8845 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8846 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8847 //                      rsurface.batchnormal3f_bufferoffset = 0;
8848                         for (j = 0;j < batchnumvertices;j++)
8849                         {
8850                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8851                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8852                         }
8853                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8854                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8855                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8856                         {
8857 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8858 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8859 //                              rsurface.batchsvector3f_bufferoffset = 0;
8860 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8861 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8862 //                              rsurface.batchtvector3f_bufferoffset = 0;
8863                                 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);
8864                         }
8865                         break;
8866                 case Q3DEFORM_MOVE:
8867                         // deform vertex array
8868                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8869                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8870                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8871                         VectorScale(deform->parms, scale, waveparms);
8872 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8873 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8874 //                      rsurface.batchvertex3f_bufferoffset = 0;
8875                         for (j = 0;j < batchnumvertices;j++)
8876                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8877                         break;
8878                 }
8879         }
8880
8881         // generate texcoords based on the chosen texcoord source
8882         switch(rsurface.texture->tcgen.tcgen)
8883         {
8884         default:
8885         case Q3TCGEN_TEXTURE:
8886                 break;
8887         case Q3TCGEN_LIGHTMAP:
8888 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8889 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8890 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8891                 if (rsurface.batchtexcoordlightmap2f)
8892                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8893                 break;
8894         case Q3TCGEN_VECTOR:
8895 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8896 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8897 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8898                 for (j = 0;j < batchnumvertices;j++)
8899                 {
8900                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8901                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8902                 }
8903                 break;
8904         case Q3TCGEN_ENVIRONMENT:
8905                 // make environment reflections using a spheremap
8906                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8907                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8908                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8909                 for (j = 0;j < batchnumvertices;j++)
8910                 {
8911                         // identical to Q3A's method, but executed in worldspace so
8912                         // carried models can be shiny too
8913
8914                         float viewer[3], d, reflected[3], worldreflected[3];
8915
8916                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8917                         // VectorNormalize(viewer);
8918
8919                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8920
8921                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8922                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8923                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8924                         // note: this is proportinal to viewer, so we can normalize later
8925
8926                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8927                         VectorNormalize(worldreflected);
8928
8929                         // note: this sphere map only uses world x and z!
8930                         // so positive and negative y will LOOK THE SAME.
8931                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8932                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8933                 }
8934                 break;
8935         }
8936         // the only tcmod that needs software vertex processing is turbulent, so
8937         // check for it here and apply the changes if needed
8938         // and we only support that as the first one
8939         // (handling a mixture of turbulent and other tcmods would be problematic
8940         //  without punting it entirely to a software path)
8941         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8942         {
8943                 amplitude = rsurface.texture->tcmods[0].parms[1];
8944                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8945 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948                 for (j = 0;j < batchnumvertices;j++)
8949                 {
8950                         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);
8951                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8952                 }
8953         }
8954
8955         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8956         {
8957                 // convert the modified arrays to vertex structs
8958 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8959 //              rsurface.batchvertexmeshbuffer = NULL;
8960                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8961                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8962                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8963                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8964                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8965                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8966                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8967                 {
8968                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969                         {
8970                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8971                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8972                         }
8973                 }
8974                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8975                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8976                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8977                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8978                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8979                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8980                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8981                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8982                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8983         }
8984 }
8985
8986 void RSurf_DrawBatch(void)
8987 {
8988         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8989         // through the pipeline, killing it earlier in the pipeline would have
8990         // per-surface overhead rather than per-batch overhead, so it's best to
8991         // reject it here, before it hits glDraw.
8992         if (rsurface.batchnumtriangles == 0)
8993                 return;
8994 #if 0
8995         // batch debugging code
8996         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8997         {
8998                 int i;
8999                 int j;
9000                 int c;
9001                 const int *e;
9002                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9003                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9004                 {
9005                         c = e[i];
9006                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9007                         {
9008                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9009                                 {
9010                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9011                                                 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);
9012                                         break;
9013                                 }
9014                         }
9015                 }
9016         }
9017 #endif
9018         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);
9019 }
9020
9021 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9022 {
9023         // pick the closest matching water plane
9024         int planeindex, vertexindex, bestplaneindex = -1;
9025         float d, bestd;
9026         vec3_t vert;
9027         const float *v;
9028         r_waterstate_waterplane_t *p;
9029         qboolean prepared = false;
9030         bestd = 0;
9031         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9032         {
9033                 if(p->camera_entity != rsurface.texture->camera_entity)
9034                         continue;
9035                 d = 0;
9036                 if(!prepared)
9037                 {
9038                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9039                         prepared = true;
9040                         if(rsurface.batchnumvertices == 0)
9041                                 break;
9042                 }
9043                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9044                 {
9045                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9046                         d += fabs(PlaneDiff(vert, &p->plane));
9047                 }
9048                 if (bestd > d || bestplaneindex < 0)
9049                 {
9050                         bestd = d;
9051                         bestplaneindex = planeindex;
9052                 }
9053         }
9054         return bestplaneindex;
9055         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9056         // this situation though, as it might be better to render single larger
9057         // batches with useless stuff (backface culled for example) than to
9058         // render multiple smaller batches
9059 }
9060
9061 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9062 {
9063         int i;
9064         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9065         rsurface.passcolor4f_vertexbuffer = 0;
9066         rsurface.passcolor4f_bufferoffset = 0;
9067         for (i = 0;i < rsurface.batchnumvertices;i++)
9068                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9069 }
9070
9071 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9072 {
9073         int i;
9074         float f;
9075         const float *v;
9076         const float *c;
9077         float *c2;
9078         if (rsurface.passcolor4f)
9079         {
9080                 // generate color arrays
9081                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9082                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9083                 rsurface.passcolor4f_vertexbuffer = 0;
9084                 rsurface.passcolor4f_bufferoffset = 0;
9085                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9086                 {
9087                         f = RSurf_FogVertex(v);
9088                         c2[0] = c[0] * f;
9089                         c2[1] = c[1] * f;
9090                         c2[2] = c[2] * f;
9091                         c2[3] = c[3];
9092                 }
9093         }
9094         else
9095         {
9096                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9097                 rsurface.passcolor4f_vertexbuffer = 0;
9098                 rsurface.passcolor4f_bufferoffset = 0;
9099                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9100                 {
9101                         f = RSurf_FogVertex(v);
9102                         c2[0] = f;
9103                         c2[1] = f;
9104                         c2[2] = f;
9105                         c2[3] = 1;
9106                 }
9107         }
9108 }
9109
9110 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9111 {
9112         int i;
9113         float f;
9114         const float *v;
9115         const float *c;
9116         float *c2;
9117         if (!rsurface.passcolor4f)
9118                 return;
9119         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9120         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9121         rsurface.passcolor4f_vertexbuffer = 0;
9122         rsurface.passcolor4f_bufferoffset = 0;
9123         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)
9124         {
9125                 f = RSurf_FogVertex(v);
9126                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9127                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9128                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9129                 c2[3] = c[3];
9130         }
9131 }
9132
9133 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9134 {
9135         int i;
9136         const float *c;
9137         float *c2;
9138         if (!rsurface.passcolor4f)
9139                 return;
9140         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9141         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9142         rsurface.passcolor4f_vertexbuffer = 0;
9143         rsurface.passcolor4f_bufferoffset = 0;
9144         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9145         {
9146                 c2[0] = c[0] * r;
9147                 c2[1] = c[1] * g;
9148                 c2[2] = c[2] * b;
9149                 c2[3] = c[3] * a;
9150         }
9151 }
9152
9153 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9154 {
9155         int i;
9156         const float *c;
9157         float *c2;
9158         if (!rsurface.passcolor4f)
9159                 return;
9160         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9161         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9162         rsurface.passcolor4f_vertexbuffer = 0;
9163         rsurface.passcolor4f_bufferoffset = 0;
9164         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9165         {
9166                 c2[0] = c[0] + r_refdef.scene.ambient;
9167                 c2[1] = c[1] + r_refdef.scene.ambient;
9168                 c2[2] = c[2] + r_refdef.scene.ambient;
9169                 c2[3] = c[3];
9170         }
9171 }
9172
9173 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9174 {
9175         // TODO: optimize
9176         rsurface.passcolor4f = NULL;
9177         rsurface.passcolor4f_vertexbuffer = 0;
9178         rsurface.passcolor4f_bufferoffset = 0;
9179         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9180         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9181         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9182         GL_Color(r, g, b, a);
9183         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9184         RSurf_DrawBatch();
9185 }
9186
9187 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9188 {
9189         // TODO: optimize applyfog && applycolor case
9190         // just apply fog if necessary, and tint the fog color array if necessary
9191         rsurface.passcolor4f = NULL;
9192         rsurface.passcolor4f_vertexbuffer = 0;
9193         rsurface.passcolor4f_bufferoffset = 0;
9194         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9195         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9196         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9197         GL_Color(r, g, b, a);
9198         RSurf_DrawBatch();
9199 }
9200
9201 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9202 {
9203         // TODO: optimize
9204         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9205         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9206         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9207         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9208         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9209         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9210         GL_Color(r, g, b, a);
9211         RSurf_DrawBatch();
9212 }
9213
9214 static void RSurf_DrawBatch_GL11_ClampColor(void)
9215 {
9216         int i;
9217         const float *c1;
9218         float *c2;
9219         if (!rsurface.passcolor4f)
9220                 return;
9221         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9222         {
9223                 c2[0] = bound(0.0f, c1[0], 1.0f);
9224                 c2[1] = bound(0.0f, c1[1], 1.0f);
9225                 c2[2] = bound(0.0f, c1[2], 1.0f);
9226                 c2[3] = bound(0.0f, c1[3], 1.0f);
9227         }
9228 }
9229
9230 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9231 {
9232         int i;
9233         float f;
9234         const float *v;
9235         const float *n;
9236         float *c;
9237         //vec3_t eyedir;
9238
9239         // fake shading
9240         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9241         rsurface.passcolor4f_vertexbuffer = 0;
9242         rsurface.passcolor4f_bufferoffset = 0;
9243         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)
9244         {
9245                 f = -DotProduct(r_refdef.view.forward, n);
9246                 f = max(0, f);
9247                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9248                 f *= r_refdef.lightmapintensity;
9249                 Vector4Set(c, f, f, f, 1);
9250         }
9251 }
9252
9253 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9254 {
9255         RSurf_DrawBatch_GL11_ApplyFakeLight();
9256         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9257         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9258         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9259         GL_Color(r, g, b, a);
9260         RSurf_DrawBatch();
9261 }
9262
9263 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9264 {
9265         int i;
9266         float f;
9267         float alpha;
9268         const float *v;
9269         const float *n;
9270         float *c;
9271         vec3_t ambientcolor;
9272         vec3_t diffusecolor;
9273         vec3_t lightdir;
9274         // TODO: optimize
9275         // model lighting
9276         VectorCopy(rsurface.modellight_lightdir, lightdir);
9277         f = 0.5f * r_refdef.lightmapintensity;
9278         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9279         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9280         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9281         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9282         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9283         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9284         alpha = *a;
9285         if (VectorLength2(diffusecolor) > 0)
9286         {
9287                 // q3-style directional shading
9288                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9289                 rsurface.passcolor4f_vertexbuffer = 0;
9290                 rsurface.passcolor4f_bufferoffset = 0;
9291                 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)
9292                 {
9293                         if ((f = DotProduct(n, lightdir)) > 0)
9294                                 VectorMA(ambientcolor, f, diffusecolor, c);
9295                         else
9296                                 VectorCopy(ambientcolor, c);
9297                         c[3] = alpha;
9298                 }
9299                 *r = 1;
9300                 *g = 1;
9301                 *b = 1;
9302                 *a = 1;
9303                 *applycolor = false;
9304         }
9305         else
9306         {
9307                 *r = ambientcolor[0];
9308                 *g = ambientcolor[1];
9309                 *b = ambientcolor[2];
9310                 rsurface.passcolor4f = NULL;
9311                 rsurface.passcolor4f_vertexbuffer = 0;
9312                 rsurface.passcolor4f_bufferoffset = 0;
9313         }
9314 }
9315
9316 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9317 {
9318         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9319         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9320         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9321         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9322         GL_Color(r, g, b, a);
9323         RSurf_DrawBatch();
9324 }
9325
9326 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9327 {
9328         int i;
9329         float f;
9330         const float *v;
9331         float *c;
9332
9333         // fake shading
9334         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9335         rsurface.passcolor4f_vertexbuffer = 0;
9336         rsurface.passcolor4f_bufferoffset = 0;
9337
9338         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9339         {
9340                 f = 1 - RSurf_FogVertex(v);
9341                 c[0] = r;
9342                 c[1] = g;
9343                 c[2] = b;
9344                 c[3] = f * a;
9345         }
9346 }
9347
9348 void RSurf_SetupDepthAndCulling(void)
9349 {
9350         // submodels are biased to avoid z-fighting with world surfaces that they
9351         // may be exactly overlapping (avoids z-fighting artifacts on certain
9352         // doors and things in Quake maps)
9353         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9354         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9355         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9356         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9357 }
9358
9359 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9360 {
9361         // transparent sky would be ridiculous
9362         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9363                 return;
9364         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9365         skyrenderlater = true;
9366         RSurf_SetupDepthAndCulling();
9367         GL_DepthMask(true);
9368         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9369         // skymasking on them, and Quake3 never did sky masking (unlike
9370         // software Quake and software Quake2), so disable the sky masking
9371         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9372         // and skymasking also looks very bad when noclipping outside the
9373         // level, so don't use it then either.
9374         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9375         {
9376                 R_Mesh_ResetTextureState();
9377                 if (skyrendermasked)
9378                 {
9379                         R_SetupShader_DepthOrShadow();
9380                         // depth-only (masking)
9381                         GL_ColorMask(0,0,0,0);
9382                         // just to make sure that braindead drivers don't draw
9383                         // anything despite that colormask...
9384                         GL_BlendFunc(GL_ZERO, GL_ONE);
9385                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9386                         if (rsurface.batchvertex3fbuffer)
9387                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9388                         else
9389                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9390                 }
9391                 else
9392                 {
9393                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9394                         // fog sky
9395                         GL_BlendFunc(GL_ONE, GL_ZERO);
9396                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9397                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9398                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9399                 }
9400                 RSurf_DrawBatch();
9401                 if (skyrendermasked)
9402                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9403         }
9404         R_Mesh_ResetTextureState();
9405         GL_Color(1, 1, 1, 1);
9406 }
9407
9408 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9409 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9410 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9411 {
9412         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9413                 return;
9414         if (prepass)
9415         {
9416                 // render screenspace normalmap to texture
9417                 GL_DepthMask(true);
9418                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9419                 RSurf_DrawBatch();
9420                 return;
9421         }
9422
9423         // bind lightmap texture
9424
9425         // water/refraction/reflection/camera surfaces have to be handled specially
9426         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9427         {
9428                 int start, end, startplaneindex;
9429                 for (start = 0;start < texturenumsurfaces;start = end)
9430                 {
9431                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9432                         if(startplaneindex < 0)
9433                         {
9434                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9435                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9436                                 end = start + 1;
9437                                 continue;
9438                         }
9439                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9440                                 ;
9441                         // now that we have a batch using the same planeindex, render it
9442                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9443                         {
9444                                 // render water or distortion background
9445                                 GL_DepthMask(true);
9446                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9447                                 RSurf_DrawBatch();
9448                                 // blend surface on top
9449                                 GL_DepthMask(false);
9450                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9451                                 RSurf_DrawBatch();
9452                         }
9453                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9454                         {
9455                                 // render surface with reflection texture as input
9456                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9457                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9458                                 RSurf_DrawBatch();
9459                         }
9460                 }
9461                 return;
9462         }
9463
9464         // render surface batch normally
9465         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9466         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9467         RSurf_DrawBatch();
9468 }
9469
9470 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9471 {
9472         // OpenGL 1.3 path - anything not completely ancient
9473         qboolean applycolor;
9474         qboolean applyfog;
9475         int layerindex;
9476         const texturelayer_t *layer;
9477         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);
9478         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9479
9480         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9481         {
9482                 vec4_t layercolor;
9483                 int layertexrgbscale;
9484                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9485                 {
9486                         if (layerindex == 0)
9487                                 GL_AlphaTest(true);
9488                         else
9489                         {
9490                                 GL_AlphaTest(false);
9491                                 GL_DepthFunc(GL_EQUAL);
9492                         }
9493                 }
9494                 GL_DepthMask(layer->depthmask && writedepth);
9495                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9496                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9497                 {
9498                         layertexrgbscale = 4;
9499                         VectorScale(layer->color, 0.25f, layercolor);
9500                 }
9501                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9502                 {
9503                         layertexrgbscale = 2;
9504                         VectorScale(layer->color, 0.5f, layercolor);
9505                 }
9506                 else
9507                 {
9508                         layertexrgbscale = 1;
9509                         VectorScale(layer->color, 1.0f, layercolor);
9510                 }
9511                 layercolor[3] = layer->color[3];
9512                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9513                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9514                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9515                 switch (layer->type)
9516                 {
9517                 case TEXTURELAYERTYPE_LITTEXTURE:
9518                         // single-pass lightmapped texture with 2x rgbscale
9519                         R_Mesh_TexBind(0, r_texture_white);
9520                         R_Mesh_TexMatrix(0, NULL);
9521                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9522                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9523                         R_Mesh_TexBind(1, layer->texture);
9524                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9525                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9526                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9527                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9528                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9529                         else if (FAKELIGHT_ENABLED)
9530                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9531                         else if (rsurface.uselightmaptexture)
9532                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9533                         else
9534                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9535                         break;
9536                 case TEXTURELAYERTYPE_TEXTURE:
9537                         // singletexture unlit texture with transparency support
9538                         R_Mesh_TexBind(0, layer->texture);
9539                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9540                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9541                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9542                         R_Mesh_TexBind(1, 0);
9543                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9544                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9545                         break;
9546                 case TEXTURELAYERTYPE_FOG:
9547                         // singletexture fogging
9548                         if (layer->texture)
9549                         {
9550                                 R_Mesh_TexBind(0, layer->texture);
9551                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9552                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9553                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9554                         }
9555                         else
9556                         {
9557                                 R_Mesh_TexBind(0, 0);
9558                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9559                         }
9560                         R_Mesh_TexBind(1, 0);
9561                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9562                         // generate a color array for the fog pass
9563                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9564                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9565                         RSurf_DrawBatch();
9566                         break;
9567                 default:
9568                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9569                 }
9570         }
9571         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9572         {
9573                 GL_DepthFunc(GL_LEQUAL);
9574                 GL_AlphaTest(false);
9575         }
9576 }
9577
9578 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9579 {
9580         // OpenGL 1.1 - crusty old voodoo path
9581         qboolean applyfog;
9582         int layerindex;
9583         const texturelayer_t *layer;
9584         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);
9585         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9586
9587         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9588         {
9589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9590                 {
9591                         if (layerindex == 0)
9592                                 GL_AlphaTest(true);
9593                         else
9594                         {
9595                                 GL_AlphaTest(false);
9596                                 GL_DepthFunc(GL_EQUAL);
9597                         }
9598                 }
9599                 GL_DepthMask(layer->depthmask && writedepth);
9600                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9601                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9602                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9603                 switch (layer->type)
9604                 {
9605                 case TEXTURELAYERTYPE_LITTEXTURE:
9606                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9607                         {
9608                                 // two-pass lit texture with 2x rgbscale
9609                                 // first the lightmap pass
9610                                 R_Mesh_TexBind(0, r_texture_white);
9611                                 R_Mesh_TexMatrix(0, NULL);
9612                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9613                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9614                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9615                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9616                                 else if (FAKELIGHT_ENABLED)
9617                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9618                                 else if (rsurface.uselightmaptexture)
9619                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9620                                 else
9621                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9622                                 // then apply the texture to it
9623                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9624                                 R_Mesh_TexBind(0, layer->texture);
9625                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9626                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9627                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9628                                 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);
9629                         }
9630                         else
9631                         {
9632                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9633                                 R_Mesh_TexBind(0, layer->texture);
9634                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9635                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9636                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9637                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9638                                         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);
9639                                 else
9640                                         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);
9641                         }
9642                         break;
9643                 case TEXTURELAYERTYPE_TEXTURE:
9644                         // singletexture unlit texture with transparency support
9645                         R_Mesh_TexBind(0, layer->texture);
9646                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9647                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9648                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9649                         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);
9650                         break;
9651                 case TEXTURELAYERTYPE_FOG:
9652                         // singletexture fogging
9653                         if (layer->texture)
9654                         {
9655                                 R_Mesh_TexBind(0, layer->texture);
9656                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9657                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9658                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9659                         }
9660                         else
9661                         {
9662                                 R_Mesh_TexBind(0, 0);
9663                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9664                         }
9665                         // generate a color array for the fog pass
9666                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9667                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9668                         RSurf_DrawBatch();
9669                         break;
9670                 default:
9671                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9672                 }
9673         }
9674         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9675         {
9676                 GL_DepthFunc(GL_LEQUAL);
9677                 GL_AlphaTest(false);
9678         }
9679 }
9680
9681 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9682 {
9683         int vi;
9684         int j;
9685         r_vertexgeneric_t *batchvertex;
9686         float c[4];
9687
9688 //      R_Mesh_ResetTextureState();
9689         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9690
9691         if(rsurface.texture && rsurface.texture->currentskinframe)
9692         {
9693                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9694                 c[3] *= rsurface.texture->currentalpha;
9695         }
9696         else
9697         {
9698                 c[0] = 1;
9699                 c[1] = 0;
9700                 c[2] = 1;
9701                 c[3] = 1;
9702         }
9703
9704         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9705         {
9706                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9707                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9708                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9709         }
9710
9711         // brighten it up (as texture value 127 means "unlit")
9712         c[0] *= 2 * r_refdef.view.colorscale;
9713         c[1] *= 2 * r_refdef.view.colorscale;
9714         c[2] *= 2 * r_refdef.view.colorscale;
9715
9716         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9717                 c[3] *= r_wateralpha.value;
9718
9719         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9720         {
9721                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9722                 GL_DepthMask(false);
9723         }
9724         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9725         {
9726                 GL_BlendFunc(GL_ONE, GL_ONE);
9727                 GL_DepthMask(false);
9728         }
9729         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9730         {
9731                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9732                 GL_DepthMask(false);
9733         }
9734         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9735         {
9736                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9737                 GL_DepthMask(false);
9738         }
9739         else
9740         {
9741                 GL_BlendFunc(GL_ONE, GL_ZERO);
9742                 GL_DepthMask(writedepth);
9743         }
9744
9745         if (r_showsurfaces.integer == 3)
9746         {
9747                 rsurface.passcolor4f = NULL;
9748
9749                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9750                 {
9751                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9752
9753                         rsurface.passcolor4f = NULL;
9754                         rsurface.passcolor4f_vertexbuffer = 0;
9755                         rsurface.passcolor4f_bufferoffset = 0;
9756                 }
9757                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9758                 {
9759                         qboolean applycolor = true;
9760                         float one = 1.0;
9761
9762                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9763
9764                         r_refdef.lightmapintensity = 1;
9765                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9766                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9767                 }
9768                 else if (FAKELIGHT_ENABLED)
9769                 {
9770                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9771
9772                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9773                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9774                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9775                 }
9776                 else
9777                 {
9778                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9779
9780                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9781                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9782                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9783                 }
9784
9785                 if(!rsurface.passcolor4f)
9786                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9787
9788                 RSurf_DrawBatch_GL11_ApplyAmbient();
9789                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9790                 if(r_refdef.fogenabled)
9791                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9792                 RSurf_DrawBatch_GL11_ClampColor();
9793
9794                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9795                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9796                 RSurf_DrawBatch();
9797         }
9798         else if (!r_refdef.view.showdebug)
9799         {
9800                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9801                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9802                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9803                 {
9804                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9805                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9806                 }
9807                 R_Mesh_PrepareVertices_Generic_Unlock();
9808                 RSurf_DrawBatch();
9809         }
9810         else if (r_showsurfaces.integer == 4)
9811         {
9812                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9813                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9814                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9815                 {
9816                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9817                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9818                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9819                 }
9820                 R_Mesh_PrepareVertices_Generic_Unlock();
9821                 RSurf_DrawBatch();
9822         }
9823         else if (r_showsurfaces.integer == 2)
9824         {
9825                 const int *e;
9826                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9827                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9828                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9829                 {
9830                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9831                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9832                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9833                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9834                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9835                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9836                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9837                 }
9838                 R_Mesh_PrepareVertices_Generic_Unlock();
9839                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9840         }
9841         else
9842         {
9843                 int texturesurfaceindex;
9844                 int k;
9845                 const msurface_t *surface;
9846                 float surfacecolor4f[4];
9847                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9848                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9849                 vi = 0;
9850                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9851                 {
9852                         surface = texturesurfacelist[texturesurfaceindex];
9853                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9854                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9855                         for (j = 0;j < surface->num_vertices;j++)
9856                         {
9857                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9858                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9859                                 vi++;
9860                         }
9861                 }
9862                 R_Mesh_PrepareVertices_Generic_Unlock();
9863                 RSurf_DrawBatch();
9864         }
9865 }
9866
9867 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9868 {
9869         CHECKGLERROR
9870         RSurf_SetupDepthAndCulling();
9871         if (r_showsurfaces.integer)
9872         {
9873                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9874                 return;
9875         }
9876         switch (vid.renderpath)
9877         {
9878         case RENDERPATH_GL20:
9879         case RENDERPATH_D3D9:
9880         case RENDERPATH_D3D10:
9881         case RENDERPATH_D3D11:
9882         case RENDERPATH_SOFT:
9883         case RENDERPATH_GLES2:
9884                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9885                 break;
9886         case RENDERPATH_GL13:
9887                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9888                 break;
9889         case RENDERPATH_GL11:
9890                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9891                 break;
9892         }
9893         CHECKGLERROR
9894 }
9895
9896 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9897 {
9898         CHECKGLERROR
9899         RSurf_SetupDepthAndCulling();
9900         if (r_showsurfaces.integer)
9901         {
9902                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9903                 return;
9904         }
9905         switch (vid.renderpath)
9906         {
9907         case RENDERPATH_GL20:
9908         case RENDERPATH_D3D9:
9909         case RENDERPATH_D3D10:
9910         case RENDERPATH_D3D11:
9911         case RENDERPATH_SOFT:
9912         case RENDERPATH_GLES2:
9913                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9914                 break;
9915         case RENDERPATH_GL13:
9916                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9917                 break;
9918         case RENDERPATH_GL11:
9919                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9920                 break;
9921         }
9922         CHECKGLERROR
9923 }
9924
9925 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9926 {
9927         int i, j;
9928         int texturenumsurfaces, endsurface;
9929         texture_t *texture;
9930         const msurface_t *surface;
9931 #define MAXBATCH_TRANSPARENTSURFACES 256
9932         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9933
9934         // if the model is static it doesn't matter what value we give for
9935         // wantnormals and wanttangents, so this logic uses only rules applicable
9936         // to a model, knowing that they are meaningless otherwise
9937         if (ent == r_refdef.scene.worldentity)
9938                 RSurf_ActiveWorldEntity();
9939         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9940                 RSurf_ActiveModelEntity(ent, false, false, false);
9941         else
9942         {
9943                 switch (vid.renderpath)
9944                 {
9945                 case RENDERPATH_GL20:
9946                 case RENDERPATH_D3D9:
9947                 case RENDERPATH_D3D10:
9948                 case RENDERPATH_D3D11:
9949                 case RENDERPATH_SOFT:
9950                 case RENDERPATH_GLES2:
9951                         RSurf_ActiveModelEntity(ent, true, true, false);
9952                         break;
9953                 case RENDERPATH_GL13:
9954                 case RENDERPATH_GL11:
9955                         RSurf_ActiveModelEntity(ent, true, false, false);
9956                         break;
9957                 }
9958         }
9959
9960         if (r_transparentdepthmasking.integer)
9961         {
9962                 qboolean setup = false;
9963                 for (i = 0;i < numsurfaces;i = j)
9964                 {
9965                         j = i + 1;
9966                         surface = rsurface.modelsurfaces + surfacelist[i];
9967                         texture = surface->texture;
9968                         rsurface.texture = R_GetCurrentTexture(texture);
9969                         rsurface.lightmaptexture = NULL;
9970                         rsurface.deluxemaptexture = NULL;
9971                         rsurface.uselightmaptexture = false;
9972                         // scan ahead until we find a different texture
9973                         endsurface = min(i + 1024, numsurfaces);
9974                         texturenumsurfaces = 0;
9975                         texturesurfacelist[texturenumsurfaces++] = surface;
9976                         for (;j < endsurface;j++)
9977                         {
9978                                 surface = rsurface.modelsurfaces + surfacelist[j];
9979                                 if (texture != surface->texture)
9980                                         break;
9981                                 texturesurfacelist[texturenumsurfaces++] = surface;
9982                         }
9983                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9984                                 continue;
9985                         // render the range of surfaces as depth
9986                         if (!setup)
9987                         {
9988                                 setup = true;
9989                                 GL_ColorMask(0,0,0,0);
9990                                 GL_Color(1,1,1,1);
9991                                 GL_DepthTest(true);
9992                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9993                                 GL_DepthMask(true);
9994 //                              R_Mesh_ResetTextureState();
9995                                 R_SetupShader_DepthOrShadow();
9996                         }
9997                         RSurf_SetupDepthAndCulling();
9998                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9999                         if (rsurface.batchvertex3fbuffer)
10000                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10001                         else
10002                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10003                         RSurf_DrawBatch();
10004                 }
10005                 if (setup)
10006                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10007         }
10008
10009         for (i = 0;i < numsurfaces;i = j)
10010         {
10011                 j = i + 1;
10012                 surface = rsurface.modelsurfaces + surfacelist[i];
10013                 texture = surface->texture;
10014                 rsurface.texture = R_GetCurrentTexture(texture);
10015                 // scan ahead until we find a different texture
10016                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10017                 texturenumsurfaces = 0;
10018                 texturesurfacelist[texturenumsurfaces++] = surface;
10019                 if(FAKELIGHT_ENABLED)
10020                 {
10021                         rsurface.lightmaptexture = NULL;
10022                         rsurface.deluxemaptexture = NULL;
10023                         rsurface.uselightmaptexture = false;
10024                         for (;j < endsurface;j++)
10025                         {
10026                                 surface = rsurface.modelsurfaces + surfacelist[j];
10027                                 if (texture != surface->texture)
10028                                         break;
10029                                 texturesurfacelist[texturenumsurfaces++] = surface;
10030                         }
10031                 }
10032                 else
10033                 {
10034                         rsurface.lightmaptexture = surface->lightmaptexture;
10035                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10036                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10037                         for (;j < endsurface;j++)
10038                         {
10039                                 surface = rsurface.modelsurfaces + surfacelist[j];
10040                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10041                                         break;
10042                                 texturesurfacelist[texturenumsurfaces++] = surface;
10043                         }
10044                 }
10045                 // render the range of surfaces
10046                 if (ent == r_refdef.scene.worldentity)
10047                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10048                 else
10049                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10050         }
10051         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10052 }
10053
10054 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10055 {
10056         // transparent surfaces get pushed off into the transparent queue
10057         int surfacelistindex;
10058         const msurface_t *surface;
10059         vec3_t tempcenter, center;
10060         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10061         {
10062                 surface = texturesurfacelist[surfacelistindex];
10063                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10064                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10065                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10066                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10067                 if (queueentity->transparent_offset) // transparent offset
10068                 {
10069                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10070                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10071                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10072                 }
10073                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10074         }
10075 }
10076
10077 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10078 {
10079         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10080                 return;
10081         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10082                 return;
10083         RSurf_SetupDepthAndCulling();
10084         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10085         if (rsurface.batchvertex3fbuffer)
10086                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10087         else
10088                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10089         RSurf_DrawBatch();
10090 }
10091
10092 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10093 {
10094         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10095         CHECKGLERROR
10096         if (depthonly)
10097                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10098         else if (prepass)
10099         {
10100                 if (!rsurface.texture->currentnumlayers)
10101                         return;
10102                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10103                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10104                 else
10105                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10106         }
10107         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10108                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10109         else if (!rsurface.texture->currentnumlayers)
10110                 return;
10111         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10112         {
10113                 // in the deferred case, transparent surfaces were queued during prepass
10114                 if (!r_shadow_usingdeferredprepass)
10115                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10116         }
10117         else
10118         {
10119                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10120                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10121         }
10122         CHECKGLERROR
10123 }
10124
10125 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10126 {
10127         int i, j;
10128         texture_t *texture;
10129         R_FrameData_SetMark();
10130         // break the surface list down into batches by texture and use of lightmapping
10131         for (i = 0;i < numsurfaces;i = j)
10132         {
10133                 j = i + 1;
10134                 // texture is the base texture pointer, rsurface.texture is the
10135                 // current frame/skin the texture is directing us to use (for example
10136                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10137                 // use skin 1 instead)
10138                 texture = surfacelist[i]->texture;
10139                 rsurface.texture = R_GetCurrentTexture(texture);
10140                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10141                 {
10142                         // if this texture is not the kind we want, skip ahead to the next one
10143                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10144                                 ;
10145                         continue;
10146                 }
10147                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10148                 {
10149                         rsurface.lightmaptexture = NULL;
10150                         rsurface.deluxemaptexture = NULL;
10151                         rsurface.uselightmaptexture = false;
10152                         // simply scan ahead until we find a different texture or lightmap state
10153                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10154                                 ;
10155                 }
10156                 else
10157                 {
10158                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10159                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10160                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10161                         // simply scan ahead until we find a different texture or lightmap state
10162                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10163                                 ;
10164                 }
10165                 // render the range of surfaces
10166                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10167         }
10168         R_FrameData_ReturnToMark();
10169 }
10170
10171 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10172 {
10173         CHECKGLERROR
10174         if (depthonly)
10175                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10176         else if (prepass)
10177         {
10178                 if (!rsurface.texture->currentnumlayers)
10179                         return;
10180                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10181                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10182                 else
10183                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10184         }
10185         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10186                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10187         else if (!rsurface.texture->currentnumlayers)
10188                 return;
10189         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10190         {
10191                 // in the deferred case, transparent surfaces were queued during prepass
10192                 if (!r_shadow_usingdeferredprepass)
10193                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10194         }
10195         else
10196         {
10197                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10198                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10199         }
10200         CHECKGLERROR
10201 }
10202
10203 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10204 {
10205         int i, j;
10206         texture_t *texture;
10207         R_FrameData_SetMark();
10208         // break the surface list down into batches by texture and use of lightmapping
10209         for (i = 0;i < numsurfaces;i = j)
10210         {
10211                 j = i + 1;
10212                 // texture is the base texture pointer, rsurface.texture is the
10213                 // current frame/skin the texture is directing us to use (for example
10214                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10215                 // use skin 1 instead)
10216                 texture = surfacelist[i]->texture;
10217                 rsurface.texture = R_GetCurrentTexture(texture);
10218                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10219                 {
10220                         // if this texture is not the kind we want, skip ahead to the next one
10221                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10222                                 ;
10223                         continue;
10224                 }
10225                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10226                 {
10227                         rsurface.lightmaptexture = NULL;
10228                         rsurface.deluxemaptexture = NULL;
10229                         rsurface.uselightmaptexture = false;
10230                         // simply scan ahead until we find a different texture or lightmap state
10231                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10232                                 ;
10233                 }
10234                 else
10235                 {
10236                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10237                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10238                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10239                         // simply scan ahead until we find a different texture or lightmap state
10240                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10241                                 ;
10242                 }
10243                 // render the range of surfaces
10244                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10245         }
10246         R_FrameData_ReturnToMark();
10247 }
10248
10249 float locboxvertex3f[6*4*3] =
10250 {
10251         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10252         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10253         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10254         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10255         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10256         1,0,0, 0,0,0, 0,1,0, 1,1,0
10257 };
10258
10259 unsigned short locboxelements[6*2*3] =
10260 {
10261          0, 1, 2, 0, 2, 3,
10262          4, 5, 6, 4, 6, 7,
10263          8, 9,10, 8,10,11,
10264         12,13,14, 12,14,15,
10265         16,17,18, 16,18,19,
10266         20,21,22, 20,22,23
10267 };
10268
10269 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10270 {
10271         int i, j;
10272         cl_locnode_t *loc = (cl_locnode_t *)ent;
10273         vec3_t mins, size;
10274         float vertex3f[6*4*3];
10275         CHECKGLERROR
10276         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10277         GL_DepthMask(false);
10278         GL_DepthRange(0, 1);
10279         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10280         GL_DepthTest(true);
10281         GL_CullFace(GL_NONE);
10282         R_EntityMatrix(&identitymatrix);
10283
10284 //      R_Mesh_ResetTextureState();
10285
10286         i = surfacelist[0];
10287         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10288                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10289                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10290                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10291
10292         if (VectorCompare(loc->mins, loc->maxs))
10293         {
10294                 VectorSet(size, 2, 2, 2);
10295                 VectorMA(loc->mins, -0.5f, size, mins);
10296         }
10297         else
10298         {
10299                 VectorCopy(loc->mins, mins);
10300                 VectorSubtract(loc->maxs, loc->mins, size);
10301         }
10302
10303         for (i = 0;i < 6*4*3;)
10304                 for (j = 0;j < 3;j++, i++)
10305                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10306
10307         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10308         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10309         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10310 }
10311
10312 void R_DrawLocs(void)
10313 {
10314         int index;
10315         cl_locnode_t *loc, *nearestloc;
10316         vec3_t center;
10317         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10318         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10319         {
10320                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10321                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10322         }
10323 }
10324
10325 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10326 {
10327         if (decalsystem->decals)
10328                 Mem_Free(decalsystem->decals);
10329         memset(decalsystem, 0, sizeof(*decalsystem));
10330 }
10331
10332 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
10333 {
10334         tridecal_t *decal;
10335         tridecal_t *decals;
10336         int i;
10337
10338         // expand or initialize the system
10339         if (decalsystem->maxdecals <= decalsystem->numdecals)
10340         {
10341                 decalsystem_t old = *decalsystem;
10342                 qboolean useshortelements;
10343                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10344                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10345                 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)));
10346                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10347                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10348                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10349                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10350                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10351                 if (decalsystem->numdecals)
10352                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10353                 if (old.decals)
10354                         Mem_Free(old.decals);
10355                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10356                         decalsystem->element3i[i] = i;
10357                 if (useshortelements)
10358                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10359                                 decalsystem->element3s[i] = i;
10360         }
10361
10362         // grab a decal and search for another free slot for the next one
10363         decals = decalsystem->decals;
10364         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10365         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10366                 ;
10367         decalsystem->freedecal = i;
10368         if (decalsystem->numdecals <= i)
10369                 decalsystem->numdecals = i + 1;
10370
10371         // initialize the decal
10372         decal->lived = 0;
10373         decal->triangleindex = triangleindex;
10374         decal->surfaceindex = surfaceindex;
10375         decal->decalsequence = decalsequence;
10376         decal->color4f[0][0] = c0[0];
10377         decal->color4f[0][1] = c0[1];
10378         decal->color4f[0][2] = c0[2];
10379         decal->color4f[0][3] = 1;
10380         decal->color4f[1][0] = c1[0];
10381         decal->color4f[1][1] = c1[1];
10382         decal->color4f[1][2] = c1[2];
10383         decal->color4f[1][3] = 1;
10384         decal->color4f[2][0] = c2[0];
10385         decal->color4f[2][1] = c2[1];
10386         decal->color4f[2][2] = c2[2];
10387         decal->color4f[2][3] = 1;
10388         decal->vertex3f[0][0] = v0[0];
10389         decal->vertex3f[0][1] = v0[1];
10390         decal->vertex3f[0][2] = v0[2];
10391         decal->vertex3f[1][0] = v1[0];
10392         decal->vertex3f[1][1] = v1[1];
10393         decal->vertex3f[1][2] = v1[2];
10394         decal->vertex3f[2][0] = v2[0];
10395         decal->vertex3f[2][1] = v2[1];
10396         decal->vertex3f[2][2] = v2[2];
10397         decal->texcoord2f[0][0] = t0[0];
10398         decal->texcoord2f[0][1] = t0[1];
10399         decal->texcoord2f[1][0] = t1[0];
10400         decal->texcoord2f[1][1] = t1[1];
10401         decal->texcoord2f[2][0] = t2[0];
10402         decal->texcoord2f[2][1] = t2[1];
10403 }
10404
10405 extern cvar_t cl_decals_bias;
10406 extern cvar_t cl_decals_models;
10407 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10408 // baseparms, parms, temps
10409 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
10410 {
10411         int cornerindex;
10412         int index;
10413         float v[9][3];
10414         const float *vertex3f;
10415         const float *normal3f;
10416         int numpoints;
10417         float points[2][9][3];
10418         float temp[3];
10419         float tc[9][2];
10420         float f;
10421         float c[9][4];
10422         const int *e;
10423
10424         e = rsurface.modelelement3i + 3*triangleindex;
10425
10426         vertex3f = rsurface.modelvertex3f;
10427         normal3f = rsurface.modelnormal3f;
10428
10429         if (normal3f)
10430         {
10431                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10432                 {
10433                         index = 3*e[cornerindex];
10434                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10435                 }
10436         }
10437         else
10438         {
10439                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10440                 {
10441                         index = 3*e[cornerindex];
10442                         VectorCopy(vertex3f + index, v[cornerindex]);
10443                 }
10444         }
10445
10446         // cull backfaces
10447         //TriangleNormal(v[0], v[1], v[2], normal);
10448         //if (DotProduct(normal, localnormal) < 0.0f)
10449         //      continue;
10450         // clip by each of the box planes formed from the projection matrix
10451         // if anything survives, we emit the decal
10452         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]);
10453         if (numpoints < 3)
10454                 return;
10455         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]);
10456         if (numpoints < 3)
10457                 return;
10458         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]);
10459         if (numpoints < 3)
10460                 return;
10461         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]);
10462         if (numpoints < 3)
10463                 return;
10464         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]);
10465         if (numpoints < 3)
10466                 return;
10467         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]);
10468         if (numpoints < 3)
10469                 return;
10470         // some part of the triangle survived, so we have to accept it...
10471         if (dynamic)
10472         {
10473                 // dynamic always uses the original triangle
10474                 numpoints = 3;
10475                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10476                 {
10477                         index = 3*e[cornerindex];
10478                         VectorCopy(vertex3f + index, v[cornerindex]);
10479                 }
10480         }
10481         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10482         {
10483                 // convert vertex positions to texcoords
10484                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10485                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10486                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10487                 // calculate distance fade from the projection origin
10488                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10489                 f = bound(0.0f, f, 1.0f);
10490                 c[cornerindex][0] = r * f;
10491                 c[cornerindex][1] = g * f;
10492                 c[cornerindex][2] = b * f;
10493                 c[cornerindex][3] = 1.0f;
10494                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10495         }
10496         if (dynamic)
10497                 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);
10498         else
10499                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10500                         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);
10501 }
10502 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10503 {
10504         matrix4x4_t projection;
10505         decalsystem_t *decalsystem;
10506         qboolean dynamic;
10507         dp_model_t *model;
10508         const msurface_t *surface;
10509         const msurface_t *surfaces;
10510         const int *surfacelist;
10511         const texture_t *texture;
10512         int numtriangles;
10513         int numsurfacelist;
10514         int surfacelistindex;
10515         int surfaceindex;
10516         int triangleindex;
10517         float localorigin[3];
10518         float localnormal[3];
10519         float localmins[3];
10520         float localmaxs[3];
10521         float localsize;
10522         //float normal[3];
10523         float planes[6][4];
10524         float angles[3];
10525         bih_t *bih;
10526         int bih_triangles_count;
10527         int bih_triangles[256];
10528         int bih_surfaces[256];
10529
10530         decalsystem = &ent->decalsystem;
10531         model = ent->model;
10532         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10533         {
10534                 R_DecalSystem_Reset(&ent->decalsystem);
10535                 return;
10536         }
10537
10538         if (!model->brush.data_leafs && !cl_decals_models.integer)
10539         {
10540                 if (decalsystem->model)
10541                         R_DecalSystem_Reset(decalsystem);
10542                 return;
10543         }
10544
10545         if (decalsystem->model != model)
10546                 R_DecalSystem_Reset(decalsystem);
10547         decalsystem->model = model;
10548
10549         RSurf_ActiveModelEntity(ent, true, false, false);
10550
10551         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10552         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10553         VectorNormalize(localnormal);
10554         localsize = worldsize*rsurface.inversematrixscale;
10555         localmins[0] = localorigin[0] - localsize;
10556         localmins[1] = localorigin[1] - localsize;
10557         localmins[2] = localorigin[2] - localsize;
10558         localmaxs[0] = localorigin[0] + localsize;
10559         localmaxs[1] = localorigin[1] + localsize;
10560         localmaxs[2] = localorigin[2] + localsize;
10561
10562         //VectorCopy(localnormal, planes[4]);
10563         //VectorVectors(planes[4], planes[2], planes[0]);
10564         AnglesFromVectors(angles, localnormal, NULL, false);
10565         AngleVectors(angles, planes[0], planes[2], planes[4]);
10566         VectorNegate(planes[0], planes[1]);
10567         VectorNegate(planes[2], planes[3]);
10568         VectorNegate(planes[4], planes[5]);
10569         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10570         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10571         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10572         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10573         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10574         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10575
10576 #if 1
10577 // works
10578 {
10579         matrix4x4_t forwardprojection;
10580         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10581         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10582 }
10583 #else
10584 // broken
10585 {
10586         float projectionvector[4][3];
10587         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10588         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10589         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10590         projectionvector[0][0] = planes[0][0] * ilocalsize;
10591         projectionvector[0][1] = planes[1][0] * ilocalsize;
10592         projectionvector[0][2] = planes[2][0] * ilocalsize;
10593         projectionvector[1][0] = planes[0][1] * ilocalsize;
10594         projectionvector[1][1] = planes[1][1] * ilocalsize;
10595         projectionvector[1][2] = planes[2][1] * ilocalsize;
10596         projectionvector[2][0] = planes[0][2] * ilocalsize;
10597         projectionvector[2][1] = planes[1][2] * ilocalsize;
10598         projectionvector[2][2] = planes[2][2] * ilocalsize;
10599         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10600         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10601         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10602         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10603 }
10604 #endif
10605
10606         dynamic = model->surfmesh.isanimated;
10607         numsurfacelist = model->nummodelsurfaces;
10608         surfacelist = model->sortedmodelsurfaces;
10609         surfaces = model->data_surfaces;
10610
10611         bih = NULL;
10612         bih_triangles_count = -1;
10613         if(!dynamic)
10614         {
10615                 if(model->render_bih.numleafs)
10616                         bih = &model->render_bih;
10617                 else if(model->collision_bih.numleafs)
10618                         bih = &model->collision_bih;
10619         }
10620         if(bih)
10621                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10622         if(bih_triangles_count == 0)
10623                 return;
10624         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10625                 return;
10626         if(bih_triangles_count > 0)
10627         {
10628                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10629                 {
10630                         surfaceindex = bih_surfaces[triangleindex];
10631                         surface = surfaces + surfaceindex;
10632                         texture = surface->texture;
10633                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10634                                 continue;
10635                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10636                                 continue;
10637                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10638                 }
10639         }
10640         else
10641         {
10642                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10643                 {
10644                         surfaceindex = surfacelist[surfacelistindex];
10645                         surface = surfaces + surfaceindex;
10646                         // check cull box first because it rejects more than any other check
10647                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10648                                 continue;
10649                         // skip transparent surfaces
10650                         texture = surface->texture;
10651                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10652                                 continue;
10653                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10654                                 continue;
10655                         numtriangles = surface->num_triangles;
10656                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10657                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10658                 }
10659         }
10660 }
10661
10662 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10663 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10664 {
10665         int renderentityindex;
10666         float worldmins[3];
10667         float worldmaxs[3];
10668         entity_render_t *ent;
10669
10670         if (!cl_decals_newsystem.integer)
10671                 return;
10672
10673         worldmins[0] = worldorigin[0] - worldsize;
10674         worldmins[1] = worldorigin[1] - worldsize;
10675         worldmins[2] = worldorigin[2] - worldsize;
10676         worldmaxs[0] = worldorigin[0] + worldsize;
10677         worldmaxs[1] = worldorigin[1] + worldsize;
10678         worldmaxs[2] = worldorigin[2] + worldsize;
10679
10680         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10681
10682         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10683         {
10684                 ent = r_refdef.scene.entities[renderentityindex];
10685                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10686                         continue;
10687
10688                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10689         }
10690 }
10691
10692 typedef struct r_decalsystem_splatqueue_s
10693 {
10694         vec3_t worldorigin;
10695         vec3_t worldnormal;
10696         float color[4];
10697         float tcrange[4];
10698         float worldsize;
10699         int decalsequence;
10700 }
10701 r_decalsystem_splatqueue_t;
10702
10703 int r_decalsystem_numqueued = 0;
10704 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10705
10706 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)
10707 {
10708         r_decalsystem_splatqueue_t *queue;
10709
10710         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10711                 return;
10712
10713         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10714         VectorCopy(worldorigin, queue->worldorigin);
10715         VectorCopy(worldnormal, queue->worldnormal);
10716         Vector4Set(queue->color, r, g, b, a);
10717         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10718         queue->worldsize = worldsize;
10719         queue->decalsequence = cl.decalsequence++;
10720 }
10721
10722 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10723 {
10724         int i;
10725         r_decalsystem_splatqueue_t *queue;
10726
10727         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10728                 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);
10729         r_decalsystem_numqueued = 0;
10730 }
10731
10732 extern cvar_t cl_decals_max;
10733 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10734 {
10735         int i;
10736         decalsystem_t *decalsystem = &ent->decalsystem;
10737         int numdecals;
10738         int killsequence;
10739         tridecal_t *decal;
10740         float frametime;
10741         float lifetime;
10742
10743         if (!decalsystem->numdecals)
10744                 return;
10745
10746         if (r_showsurfaces.integer)
10747                 return;
10748
10749         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10750         {
10751                 R_DecalSystem_Reset(decalsystem);
10752                 return;
10753         }
10754
10755         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10756         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10757
10758         if (decalsystem->lastupdatetime)
10759                 frametime = (cl.time - decalsystem->lastupdatetime);
10760         else
10761                 frametime = 0;
10762         decalsystem->lastupdatetime = cl.time;
10763         decal = decalsystem->decals;
10764         numdecals = decalsystem->numdecals;
10765
10766         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10767         {
10768                 if (decal->color4f[0][3])
10769                 {
10770                         decal->lived += frametime;
10771                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10772                         {
10773                                 memset(decal, 0, sizeof(*decal));
10774                                 if (decalsystem->freedecal > i)
10775                                         decalsystem->freedecal = i;
10776                         }
10777                 }
10778         }
10779         decal = decalsystem->decals;
10780         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10781                 numdecals--;
10782
10783         // collapse the array by shuffling the tail decals into the gaps
10784         for (;;)
10785         {
10786                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10787                         decalsystem->freedecal++;
10788                 if (decalsystem->freedecal == numdecals)
10789                         break;
10790                 decal[decalsystem->freedecal] = decal[--numdecals];
10791         }
10792
10793         decalsystem->numdecals = numdecals;
10794
10795         if (numdecals <= 0)
10796         {
10797                 // if there are no decals left, reset decalsystem
10798                 R_DecalSystem_Reset(decalsystem);
10799         }
10800 }
10801
10802 extern skinframe_t *decalskinframe;
10803 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10804 {
10805         int i;
10806         decalsystem_t *decalsystem = &ent->decalsystem;
10807         int numdecals;
10808         tridecal_t *decal;
10809         float faderate;
10810         float alpha;
10811         float *v3f;
10812         float *c4f;
10813         float *t2f;
10814         const int *e;
10815         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10816         int numtris = 0;
10817
10818         numdecals = decalsystem->numdecals;
10819         if (!numdecals)
10820                 return;
10821
10822         if (r_showsurfaces.integer)
10823                 return;
10824
10825         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10826         {
10827                 R_DecalSystem_Reset(decalsystem);
10828                 return;
10829         }
10830
10831         // if the model is static it doesn't matter what value we give for
10832         // wantnormals and wanttangents, so this logic uses only rules applicable
10833         // to a model, knowing that they are meaningless otherwise
10834         if (ent == r_refdef.scene.worldentity)
10835                 RSurf_ActiveWorldEntity();
10836         else
10837                 RSurf_ActiveModelEntity(ent, false, false, false);
10838
10839         decalsystem->lastupdatetime = cl.time;
10840         decal = decalsystem->decals;
10841
10842         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10843
10844         // update vertex positions for animated models
10845         v3f = decalsystem->vertex3f;
10846         c4f = decalsystem->color4f;
10847         t2f = decalsystem->texcoord2f;
10848         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10849         {
10850                 if (!decal->color4f[0][3])
10851                         continue;
10852
10853                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10854                         continue;
10855
10856                 // update color values for fading decals
10857                 if (decal->lived >= cl_decals_time.value)
10858                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10859                 else
10860                         alpha = 1.0f;
10861
10862                 c4f[ 0] = decal->color4f[0][0] * alpha;
10863                 c4f[ 1] = decal->color4f[0][1] * alpha;
10864                 c4f[ 2] = decal->color4f[0][2] * alpha;
10865                 c4f[ 3] = 1;
10866                 c4f[ 4] = decal->color4f[1][0] * alpha;
10867                 c4f[ 5] = decal->color4f[1][1] * alpha;
10868                 c4f[ 6] = decal->color4f[1][2] * alpha;
10869                 c4f[ 7] = 1;
10870                 c4f[ 8] = decal->color4f[2][0] * alpha;
10871                 c4f[ 9] = decal->color4f[2][1] * alpha;
10872                 c4f[10] = decal->color4f[2][2] * alpha;
10873                 c4f[11] = 1;
10874
10875                 t2f[0] = decal->texcoord2f[0][0];
10876                 t2f[1] = decal->texcoord2f[0][1];
10877                 t2f[2] = decal->texcoord2f[1][0];
10878                 t2f[3] = decal->texcoord2f[1][1];
10879                 t2f[4] = decal->texcoord2f[2][0];
10880                 t2f[5] = decal->texcoord2f[2][1];
10881
10882                 // update vertex positions for animated models
10883                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10884                 {
10885                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10886                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10887                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10888                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10889                 }
10890                 else
10891                 {
10892                         VectorCopy(decal->vertex3f[0], v3f);
10893                         VectorCopy(decal->vertex3f[1], v3f + 3);
10894                         VectorCopy(decal->vertex3f[2], v3f + 6);
10895                 }
10896
10897                 if (r_refdef.fogenabled)
10898                 {
10899                         alpha = RSurf_FogVertex(v3f);
10900                         VectorScale(c4f, alpha, c4f);
10901                         alpha = RSurf_FogVertex(v3f + 3);
10902                         VectorScale(c4f + 4, alpha, c4f + 4);
10903                         alpha = RSurf_FogVertex(v3f + 6);
10904                         VectorScale(c4f + 8, alpha, c4f + 8);
10905                 }
10906
10907                 v3f += 9;
10908                 c4f += 12;
10909                 t2f += 6;
10910                 numtris++;
10911         }
10912
10913         if (numtris > 0)
10914         {
10915                 r_refdef.stats.drawndecals += numtris;
10916
10917                 // now render the decals all at once
10918                 // (this assumes they all use one particle font texture!)
10919                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10920 //              R_Mesh_ResetTextureState();
10921                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10922                 GL_DepthMask(false);
10923                 GL_DepthRange(0, 1);
10924                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10925                 GL_DepthTest(true);
10926                 GL_CullFace(GL_NONE);
10927                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10928                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10929                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10930         }
10931 }
10932
10933 static void R_DrawModelDecals(void)
10934 {
10935         int i, numdecals;
10936
10937         // fade faster when there are too many decals
10938         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10939         for (i = 0;i < r_refdef.scene.numentities;i++)
10940                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10941
10942         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10943         for (i = 0;i < r_refdef.scene.numentities;i++)
10944                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10945                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10946
10947         R_DecalSystem_ApplySplatEntitiesQueue();
10948
10949         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10950         for (i = 0;i < r_refdef.scene.numentities;i++)
10951                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10952
10953         r_refdef.stats.totaldecals += numdecals;
10954
10955         if (r_showsurfaces.integer)
10956                 return;
10957
10958         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10959
10960         for (i = 0;i < r_refdef.scene.numentities;i++)
10961         {
10962                 if (!r_refdef.viewcache.entityvisible[i])
10963                         continue;
10964                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10965                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10966         }
10967 }
10968
10969 extern cvar_t mod_collision_bih;
10970 void R_DrawDebugModel(void)
10971 {
10972         entity_render_t *ent = rsurface.entity;
10973         int i, j, k, l, flagsmask;
10974         const msurface_t *surface;
10975         dp_model_t *model = ent->model;
10976         vec3_t v;
10977
10978         switch(vid.renderpath)
10979         {
10980         case RENDERPATH_GL11:
10981         case RENDERPATH_GL13:
10982         case RENDERPATH_GL20:
10983                 break;
10984         case RENDERPATH_D3D9:
10985                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10986                 return;
10987         case RENDERPATH_D3D10:
10988                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10989                 return;
10990         case RENDERPATH_D3D11:
10991                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10992                 return;
10993         case RENDERPATH_SOFT:
10994                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10995                 return;
10996         case RENDERPATH_GLES2:
10997                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10998                 return;
10999         }
11000
11001         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11002
11003 //      R_Mesh_ResetTextureState();
11004         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11005         GL_DepthRange(0, 1);
11006         GL_DepthTest(!r_showdisabledepthtest.integer);
11007         GL_DepthMask(false);
11008         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11009
11010         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11011         {
11012                 int triangleindex;
11013                 int bihleafindex;
11014                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11015                 const q3mbrush_t *brush;
11016                 const bih_t *bih = &model->collision_bih;
11017                 const bih_leaf_t *bihleaf;
11018                 float vertex3f[3][3];
11019                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11020                 cullbox = false;
11021                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11022                 {
11023                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11024                                 continue;
11025                         switch (bihleaf->type)
11026                         {
11027                         case BIH_BRUSH:
11028                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11029                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11030                                 {
11031                                         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);
11032                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11033                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11034                                 }
11035                                 break;
11036                         case BIH_COLLISIONTRIANGLE:
11037                                 triangleindex = bihleaf->itemindex;
11038                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11039                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11040                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11041                                 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);
11042                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11043                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11044                                 break;
11045                         case BIH_RENDERTRIANGLE:
11046                                 triangleindex = bihleaf->itemindex;
11047                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11048                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11049                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11050                                 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);
11051                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11052                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11053                                 break;
11054                         }
11055                 }
11056         }
11057
11058         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11059
11060         if (r_showtris.integer || (r_shownormals.value != 0))
11061         {
11062                 if (r_showdisabledepthtest.integer)
11063                 {
11064                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11065                         GL_DepthMask(false);
11066                 }
11067                 else
11068                 {
11069                         GL_BlendFunc(GL_ONE, GL_ZERO);
11070                         GL_DepthMask(true);
11071                 }
11072                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11073                 {
11074                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11075                                 continue;
11076                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11077                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11078                         {
11079                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11080                                 if (r_showtris.value > 0)
11081                                 {
11082                                         if (!rsurface.texture->currentlayers->depthmask)
11083                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11084                                         else if (ent == r_refdef.scene.worldentity)
11085                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11086                                         else
11087                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11088                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11089                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11090                                         RSurf_DrawBatch();
11091                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11092                                         CHECKGLERROR
11093                                 }
11094                                 if (r_shownormals.value < 0)
11095                                 {
11096                                         qglBegin(GL_LINES);
11097                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11098                                         {
11099                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11100                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11101                                                 qglVertex3f(v[0], v[1], v[2]);
11102                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11103                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11104                                                 qglVertex3f(v[0], v[1], v[2]);
11105                                         }
11106                                         qglEnd();
11107                                         CHECKGLERROR
11108                                 }
11109                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11110                                 {
11111                                         qglBegin(GL_LINES);
11112                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11113                                         {
11114                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11115                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11116                                                 qglVertex3f(v[0], v[1], v[2]);
11117                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11118                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11119                                                 qglVertex3f(v[0], v[1], v[2]);
11120                                         }
11121                                         qglEnd();
11122                                         CHECKGLERROR
11123                                         qglBegin(GL_LINES);
11124                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11125                                         {
11126                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11127                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11128                                                 qglVertex3f(v[0], v[1], v[2]);
11129                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11130                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11131                                                 qglVertex3f(v[0], v[1], v[2]);
11132                                         }
11133                                         qglEnd();
11134                                         CHECKGLERROR
11135                                         qglBegin(GL_LINES);
11136                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11137                                         {
11138                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11139                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11140                                                 qglVertex3f(v[0], v[1], v[2]);
11141                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11142                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11143                                                 qglVertex3f(v[0], v[1], v[2]);
11144                                         }
11145                                         qglEnd();
11146                                         CHECKGLERROR
11147                                 }
11148                         }
11149                 }
11150                 rsurface.texture = NULL;
11151         }
11152 }
11153
11154 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11155 int r_maxsurfacelist = 0;
11156 const msurface_t **r_surfacelist = NULL;
11157 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11158 {
11159         int i, j, endj, flagsmask;
11160         dp_model_t *model = r_refdef.scene.worldmodel;
11161         msurface_t *surfaces;
11162         unsigned char *update;
11163         int numsurfacelist = 0;
11164         if (model == NULL)
11165                 return;
11166
11167         if (r_maxsurfacelist < model->num_surfaces)
11168         {
11169                 r_maxsurfacelist = model->num_surfaces;
11170                 if (r_surfacelist)
11171                         Mem_Free((msurface_t**)r_surfacelist);
11172                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11173         }
11174
11175         RSurf_ActiveWorldEntity();
11176
11177         surfaces = model->data_surfaces;
11178         update = model->brushq1.lightmapupdateflags;
11179
11180         // update light styles on this submodel
11181         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11182         {
11183                 model_brush_lightstyleinfo_t *style;
11184                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11185                 {
11186                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11187                         {
11188                                 int *list = style->surfacelist;
11189                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11190                                 for (j = 0;j < style->numsurfaces;j++)
11191                                         update[list[j]] = true;
11192                         }
11193                 }
11194         }
11195
11196         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11197
11198         if (debug)
11199         {
11200                 R_DrawDebugModel();
11201                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11202                 return;
11203         }
11204
11205         rsurface.lightmaptexture = NULL;
11206         rsurface.deluxemaptexture = NULL;
11207         rsurface.uselightmaptexture = false;
11208         rsurface.texture = NULL;
11209         rsurface.rtlight = NULL;
11210         numsurfacelist = 0;
11211         // add visible surfaces to draw list
11212         for (i = 0;i < model->nummodelsurfaces;i++)
11213         {
11214                 j = model->sortedmodelsurfaces[i];
11215                 if (r_refdef.viewcache.world_surfacevisible[j])
11216                         r_surfacelist[numsurfacelist++] = surfaces + j;
11217         }
11218         // update lightmaps if needed
11219         if (model->brushq1.firstrender)
11220         {
11221                 model->brushq1.firstrender = false;
11222                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11223                         if (update[j])
11224                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11225         }
11226         else if (update)
11227         {
11228                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11229                         if (r_refdef.viewcache.world_surfacevisible[j])
11230                                 if (update[j])
11231                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11232         }
11233         // don't do anything if there were no surfaces
11234         if (!numsurfacelist)
11235         {
11236                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11237                 return;
11238         }
11239         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11240
11241         // add to stats if desired
11242         if (r_speeds.integer && !skysurfaces && !depthonly)
11243         {
11244                 r_refdef.stats.world_surfaces += numsurfacelist;
11245                 for (j = 0;j < numsurfacelist;j++)
11246                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11247         }
11248
11249         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11250 }
11251
11252 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11253 {
11254         int i, j, endj, flagsmask;
11255         dp_model_t *model = ent->model;
11256         msurface_t *surfaces;
11257         unsigned char *update;
11258         int numsurfacelist = 0;
11259         if (model == NULL)
11260                 return;
11261
11262         if (r_maxsurfacelist < model->num_surfaces)
11263         {
11264                 r_maxsurfacelist = model->num_surfaces;
11265                 if (r_surfacelist)
11266                         Mem_Free((msurface_t **)r_surfacelist);
11267                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11268         }
11269
11270         // if the model is static it doesn't matter what value we give for
11271         // wantnormals and wanttangents, so this logic uses only rules applicable
11272         // to a model, knowing that they are meaningless otherwise
11273         if (ent == r_refdef.scene.worldentity)
11274                 RSurf_ActiveWorldEntity();
11275         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11276                 RSurf_ActiveModelEntity(ent, false, false, false);
11277         else if (prepass)
11278                 RSurf_ActiveModelEntity(ent, true, true, true);
11279         else if (depthonly)
11280         {
11281                 switch (vid.renderpath)
11282                 {
11283                 case RENDERPATH_GL20:
11284                 case RENDERPATH_D3D9:
11285                 case RENDERPATH_D3D10:
11286                 case RENDERPATH_D3D11:
11287                 case RENDERPATH_SOFT:
11288                 case RENDERPATH_GLES2:
11289                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11290                         break;
11291                 case RENDERPATH_GL13:
11292                 case RENDERPATH_GL11:
11293                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11294                         break;
11295                 }
11296         }
11297         else
11298         {
11299                 switch (vid.renderpath)
11300                 {
11301                 case RENDERPATH_GL20:
11302                 case RENDERPATH_D3D9:
11303                 case RENDERPATH_D3D10:
11304                 case RENDERPATH_D3D11:
11305                 case RENDERPATH_SOFT:
11306                 case RENDERPATH_GLES2:
11307                         RSurf_ActiveModelEntity(ent, true, true, false);
11308                         break;
11309                 case RENDERPATH_GL13:
11310                 case RENDERPATH_GL11:
11311                         RSurf_ActiveModelEntity(ent, true, false, false);
11312                         break;
11313                 }
11314         }
11315
11316         surfaces = model->data_surfaces;
11317         update = model->brushq1.lightmapupdateflags;
11318
11319         // update light styles
11320         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11321         {
11322                 model_brush_lightstyleinfo_t *style;
11323                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11324                 {
11325                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11326                         {
11327                                 int *list = style->surfacelist;
11328                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11329                                 for (j = 0;j < style->numsurfaces;j++)
11330                                         update[list[j]] = true;
11331                         }
11332                 }
11333         }
11334
11335         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11336
11337         if (debug)
11338         {
11339                 R_DrawDebugModel();
11340                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11341                 return;
11342         }
11343
11344         rsurface.lightmaptexture = NULL;
11345         rsurface.deluxemaptexture = NULL;
11346         rsurface.uselightmaptexture = false;
11347         rsurface.texture = NULL;
11348         rsurface.rtlight = NULL;
11349         numsurfacelist = 0;
11350         // add visible surfaces to draw list
11351         for (i = 0;i < model->nummodelsurfaces;i++)
11352                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11353         // don't do anything if there were no surfaces
11354         if (!numsurfacelist)
11355         {
11356                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11357                 return;
11358         }
11359         // update lightmaps if needed
11360         if (update)
11361         {
11362                 int updated = 0;
11363                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11364                 {
11365                         if (update[j])
11366                         {
11367                                 updated++;
11368                                 R_BuildLightMap(ent, surfaces + j);
11369                         }
11370                 }
11371         }
11372         if (update)
11373                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11374                         if (update[j])
11375                                 R_BuildLightMap(ent, surfaces + j);
11376         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11377
11378         // add to stats if desired
11379         if (r_speeds.integer && !skysurfaces && !depthonly)
11380         {
11381                 r_refdef.stats.entities_surfaces += numsurfacelist;
11382                 for (j = 0;j < numsurfacelist;j++)
11383                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11384         }
11385
11386         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11387 }
11388
11389 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11390 {
11391         static texture_t texture;
11392         static msurface_t surface;
11393         const msurface_t *surfacelist = &surface;
11394
11395         // fake enough texture and surface state to render this geometry
11396
11397         texture.update_lastrenderframe = -1; // regenerate this texture
11398         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11399         texture.currentskinframe = skinframe;
11400         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11401         texture.offsetmapping = OFFSETMAPPING_OFF;
11402         texture.offsetscale = 1;
11403         texture.specularscalemod = 1;
11404         texture.specularpowermod = 1;
11405
11406         surface.texture = &texture;
11407         surface.num_triangles = numtriangles;
11408         surface.num_firsttriangle = firsttriangle;
11409         surface.num_vertices = numvertices;
11410         surface.num_firstvertex = firstvertex;
11411
11412         // now render it
11413         rsurface.texture = R_GetCurrentTexture(surface.texture);
11414         rsurface.lightmaptexture = NULL;
11415         rsurface.deluxemaptexture = NULL;
11416         rsurface.uselightmaptexture = false;
11417         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11418 }
11419
11420 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)
11421 {
11422         static msurface_t surface;
11423         const msurface_t *surfacelist = &surface;
11424
11425         // fake enough texture and surface state to render this geometry
11426         surface.texture = texture;
11427         surface.num_triangles = numtriangles;
11428         surface.num_firsttriangle = firsttriangle;
11429         surface.num_vertices = numvertices;
11430         surface.num_firstvertex = firstvertex;
11431
11432         // now render it
11433         rsurface.texture = R_GetCurrentTexture(surface.texture);
11434         rsurface.lightmaptexture = NULL;
11435         rsurface.deluxemaptexture = NULL;
11436         rsurface.uselightmaptexture = false;
11437         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11438 }