]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
reworked r_viewscale_fpsscaling to use the time of SCR_DrawScreen
[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.25", "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", "90", "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         case RENDERPATH_GLES2:
3844                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3845                 Cvar_SetValueQuick(&gl_combine, 1);
3846                 Cvar_SetValueQuick(&r_glsl, 1);
3847                 r_loadnormalmap = true;
3848                 r_loadgloss = true;
3849                 r_loadfog = false;
3850                 break;
3851         case RENDERPATH_GL13:
3852                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3853                 Cvar_SetValueQuick(&gl_combine, 1);
3854                 Cvar_SetValueQuick(&r_glsl, 0);
3855                 r_loadnormalmap = false;
3856                 r_loadgloss = false;
3857                 r_loadfog = true;
3858                 break;
3859         case RENDERPATH_GL11:
3860                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861                 Cvar_SetValueQuick(&gl_combine, 0);
3862                 Cvar_SetValueQuick(&r_glsl, 0);
3863                 r_loadnormalmap = false;
3864                 r_loadgloss = false;
3865                 r_loadfog = true;
3866                 break;
3867         }
3868
3869         R_AnimCache_Free();
3870         R_FrameData_Reset();
3871
3872         r_numqueries = 0;
3873         r_maxqueries = 0;
3874         memset(r_queries, 0, sizeof(r_queries));
3875
3876         r_qwskincache = NULL;
3877         r_qwskincache_size = 0;
3878
3879         // due to caching of texture_t references, the collision cache must be reset
3880         Collision_Cache_Reset(true);
3881
3882         // set up r_skinframe loading system for textures
3883         memset(&r_skinframe, 0, sizeof(r_skinframe));
3884         r_skinframe.loadsequence = 1;
3885         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3886
3887         r_main_texturepool = R_AllocTexturePool();
3888         R_BuildBlankTextures();
3889         R_BuildNoTexture();
3890         if (vid.support.arb_texture_cube_map)
3891         {
3892                 R_BuildWhiteCube();
3893                 R_BuildNormalizationCube();
3894         }
3895         r_texture_fogattenuation = NULL;
3896         r_texture_fogheighttexture = NULL;
3897         r_texture_gammaramps = NULL;
3898         //r_texture_fogintensity = NULL;
3899         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3900         memset(&r_waterstate, 0, sizeof(r_waterstate));
3901         r_glsl_permutation = NULL;
3902         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3903         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3904         glslshaderstring = NULL;
3905 #ifdef SUPPORTD3D
3906         r_hlsl_permutation = NULL;
3907         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3908         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3909 #endif
3910         hlslshaderstring = NULL;
3911         memset(&r_svbsp, 0, sizeof (r_svbsp));
3912
3913         r_refdef.fogmasktable_density = 0;
3914 }
3915
3916 void gl_main_shutdown(void)
3917 {
3918         R_AnimCache_Free();
3919         R_FrameData_Reset();
3920
3921         R_Main_FreeViewCache();
3922
3923         switch(vid.renderpath)
3924         {
3925         case RENDERPATH_GL11:
3926         case RENDERPATH_GL13:
3927         case RENDERPATH_GL20:
3928         case RENDERPATH_GLES2:
3929                 if (r_maxqueries)
3930                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3931                 break;
3932         case RENDERPATH_D3D9:
3933                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3934                 break;
3935         case RENDERPATH_D3D10:
3936                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3937                 break;
3938         case RENDERPATH_D3D11:
3939                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3940                 break;
3941         case RENDERPATH_SOFT:
3942                 break;
3943         }
3944
3945         r_numqueries = 0;
3946         r_maxqueries = 0;
3947         memset(r_queries, 0, sizeof(r_queries));
3948
3949         r_qwskincache = NULL;
3950         r_qwskincache_size = 0;
3951
3952         // clear out the r_skinframe state
3953         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3954         memset(&r_skinframe, 0, sizeof(r_skinframe));
3955
3956         if (r_svbsp.nodes)
3957                 Mem_Free(r_svbsp.nodes);
3958         memset(&r_svbsp, 0, sizeof (r_svbsp));
3959         R_FreeTexturePool(&r_main_texturepool);
3960         loadingscreentexture = NULL;
3961         r_texture_blanknormalmap = NULL;
3962         r_texture_white = NULL;
3963         r_texture_grey128 = NULL;
3964         r_texture_black = NULL;
3965         r_texture_whitecube = NULL;
3966         r_texture_normalizationcube = NULL;
3967         r_texture_fogattenuation = NULL;
3968         r_texture_fogheighttexture = NULL;
3969         r_texture_gammaramps = NULL;
3970         r_texture_numcubemaps = 0;
3971         //r_texture_fogintensity = NULL;
3972         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3973         memset(&r_waterstate, 0, sizeof(r_waterstate));
3974         R_GLSL_Restart_f();
3975
3976         r_glsl_permutation = NULL;
3977         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3978         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3979         glslshaderstring = NULL;
3980 #ifdef SUPPORTD3D
3981         r_hlsl_permutation = NULL;
3982         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3983         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3984 #endif
3985         hlslshaderstring = NULL;
3986 }
3987
3988 extern void CL_ParseEntityLump(char *entitystring);
3989 void gl_main_newmap(void)
3990 {
3991         // FIXME: move this code to client
3992         char *entities, entname[MAX_QPATH];
3993         if (r_qwskincache)
3994                 Mem_Free(r_qwskincache);
3995         r_qwskincache = NULL;
3996         r_qwskincache_size = 0;
3997         if (cl.worldmodel)
3998         {
3999                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4000                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4001                 {
4002                         CL_ParseEntityLump(entities);
4003                         Mem_Free(entities);
4004                         return;
4005                 }
4006                 if (cl.worldmodel->brush.entities)
4007                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4008         }
4009         R_Main_FreeViewCache();
4010
4011         R_FrameData_Reset();
4012 }
4013
4014 void GL_Main_Init(void)
4015 {
4016         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4017
4018         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4019         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4020         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4021         if (gamemode == GAME_NEHAHRA)
4022         {
4023                 Cvar_RegisterVariable (&gl_fogenable);
4024                 Cvar_RegisterVariable (&gl_fogdensity);
4025                 Cvar_RegisterVariable (&gl_fogred);
4026                 Cvar_RegisterVariable (&gl_foggreen);
4027                 Cvar_RegisterVariable (&gl_fogblue);
4028                 Cvar_RegisterVariable (&gl_fogstart);
4029                 Cvar_RegisterVariable (&gl_fogend);
4030                 Cvar_RegisterVariable (&gl_skyclip);
4031         }
4032         Cvar_RegisterVariable(&r_motionblur);
4033         Cvar_RegisterVariable(&r_motionblur_maxblur);
4034         Cvar_RegisterVariable(&r_motionblur_bmin);
4035         Cvar_RegisterVariable(&r_motionblur_vmin);
4036         Cvar_RegisterVariable(&r_motionblur_vmax);
4037         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4038         Cvar_RegisterVariable(&r_motionblur_randomize);
4039         Cvar_RegisterVariable(&r_damageblur);
4040         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4041         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4042         Cvar_RegisterVariable(&r_equalize_entities_by);
4043         Cvar_RegisterVariable(&r_equalize_entities_to);
4044         Cvar_RegisterVariable(&r_depthfirst);
4045         Cvar_RegisterVariable(&r_useinfinitefarclip);
4046         Cvar_RegisterVariable(&r_farclip_base);
4047         Cvar_RegisterVariable(&r_farclip_world);
4048         Cvar_RegisterVariable(&r_nearclip);
4049         Cvar_RegisterVariable(&r_showbboxes);
4050         Cvar_RegisterVariable(&r_showsurfaces);
4051         Cvar_RegisterVariable(&r_showtris);
4052         Cvar_RegisterVariable(&r_shownormals);
4053         Cvar_RegisterVariable(&r_showlighting);
4054         Cvar_RegisterVariable(&r_showshadowvolumes);
4055         Cvar_RegisterVariable(&r_showcollisionbrushes);
4056         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4057         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4058         Cvar_RegisterVariable(&r_showdisabledepthtest);
4059         Cvar_RegisterVariable(&r_drawportals);
4060         Cvar_RegisterVariable(&r_drawentities);
4061         Cvar_RegisterVariable(&r_draw2d);
4062         Cvar_RegisterVariable(&r_drawworld);
4063         Cvar_RegisterVariable(&r_cullentities_trace);
4064         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4065         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4066         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4067         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4068         Cvar_RegisterVariable(&r_drawviewmodel);
4069         Cvar_RegisterVariable(&r_drawexteriormodel);
4070         Cvar_RegisterVariable(&r_speeds);
4071         Cvar_RegisterVariable(&r_fullbrights);
4072         Cvar_RegisterVariable(&r_wateralpha);
4073         Cvar_RegisterVariable(&r_dynamic);
4074         Cvar_RegisterVariable(&r_fakelight);
4075         Cvar_RegisterVariable(&r_fakelight_intensity);
4076         Cvar_RegisterVariable(&r_fullbright);
4077         Cvar_RegisterVariable(&r_shadows);
4078         Cvar_RegisterVariable(&r_shadows_darken);
4079         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4080         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4081         Cvar_RegisterVariable(&r_shadows_throwdistance);
4082         Cvar_RegisterVariable(&r_shadows_throwdirection);
4083         Cvar_RegisterVariable(&r_shadows_focus);
4084         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4085         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4086         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4087         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4088         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4089         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4090         Cvar_RegisterVariable(&r_fog_exp2);
4091         Cvar_RegisterVariable(&r_fog_clear);
4092         Cvar_RegisterVariable(&r_drawfog);
4093         Cvar_RegisterVariable(&r_transparentdepthmasking);
4094         Cvar_RegisterVariable(&r_texture_dds_load);
4095         Cvar_RegisterVariable(&r_texture_dds_save);
4096         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4097         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4098         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4099         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4100         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4101         Cvar_RegisterVariable(&r_textureunits);
4102         Cvar_RegisterVariable(&gl_combine);
4103         Cvar_RegisterVariable(&r_viewfbo);
4104         Cvar_RegisterVariable(&r_viewscale);
4105         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4106         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4107         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4108         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4109         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4110         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4111         Cvar_RegisterVariable(&r_glsl);
4112         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4113         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4114         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4115         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4116         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4117         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4118         Cvar_RegisterVariable(&r_glsl_postprocess);
4119         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4120         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4121         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4122         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4123         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4124         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4125         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4126         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4127
4128         Cvar_RegisterVariable(&r_water);
4129         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4130         Cvar_RegisterVariable(&r_water_clippingplanebias);
4131         Cvar_RegisterVariable(&r_water_refractdistort);
4132         Cvar_RegisterVariable(&r_water_reflectdistort);
4133         Cvar_RegisterVariable(&r_water_scissormode);
4134         Cvar_RegisterVariable(&r_lerpsprites);
4135         Cvar_RegisterVariable(&r_lerpmodels);
4136         Cvar_RegisterVariable(&r_lerplightstyles);
4137         Cvar_RegisterVariable(&r_waterscroll);
4138         Cvar_RegisterVariable(&r_bloom);
4139         Cvar_RegisterVariable(&r_bloom_colorscale);
4140         Cvar_RegisterVariable(&r_bloom_brighten);
4141         Cvar_RegisterVariable(&r_bloom_blur);
4142         Cvar_RegisterVariable(&r_bloom_resolution);
4143         Cvar_RegisterVariable(&r_bloom_colorexponent);
4144         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4145         Cvar_RegisterVariable(&r_hdr);
4146         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4147         Cvar_RegisterVariable(&r_hdr_glowintensity);
4148         Cvar_RegisterVariable(&r_hdr_range);
4149         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4150         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4151         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4152         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4153         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4154         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4155         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4156         Cvar_RegisterVariable(&developer_texturelogging);
4157         Cvar_RegisterVariable(&gl_lightmaps);
4158         Cvar_RegisterVariable(&r_test);
4159         Cvar_RegisterVariable(&r_glsl_saturation);
4160         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4161         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4162         Cvar_RegisterVariable(&r_framedatasize);
4163         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4164                 Cvar_SetValue("r_fullbrights", 0);
4165         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4166
4167         Cvar_RegisterVariable(&r_track_sprites);
4168         Cvar_RegisterVariable(&r_track_sprites_flags);
4169         Cvar_RegisterVariable(&r_track_sprites_scalew);
4170         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4171         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4172         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4173         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4174         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4175 }
4176
4177 extern void R_Textures_Init(void);
4178 extern void GL_Draw_Init(void);
4179 extern void GL_Main_Init(void);
4180 extern void R_Shadow_Init(void);
4181 extern void R_Sky_Init(void);
4182 extern void GL_Surf_Init(void);
4183 extern void R_Particles_Init(void);
4184 extern void R_Explosion_Init(void);
4185 extern void gl_backend_init(void);
4186 extern void Sbar_Init(void);
4187 extern void R_LightningBeams_Init(void);
4188 extern void Mod_RenderInit(void);
4189 extern void Font_Init(void);
4190
4191 void Render_Init(void)
4192 {
4193         gl_backend_init();
4194         R_Textures_Init();
4195         GL_Main_Init();
4196         Font_Init();
4197         GL_Draw_Init();
4198         R_Shadow_Init();
4199         R_Sky_Init();
4200         GL_Surf_Init();
4201         Sbar_Init();
4202         R_Particles_Init();
4203         R_Explosion_Init();
4204         R_LightningBeams_Init();
4205         Mod_RenderInit();
4206 }
4207
4208 /*
4209 ===============
4210 GL_Init
4211 ===============
4212 */
4213 extern char *ENGINE_EXTENSIONS;
4214 void GL_Init (void)
4215 {
4216         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4217         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4218         gl_version = (const char *)qglGetString(GL_VERSION);
4219         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4220
4221         if (!gl_extensions)
4222                 gl_extensions = "";
4223         if (!gl_platformextensions)
4224                 gl_platformextensions = "";
4225
4226         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4227         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4228         Con_Printf("GL_VERSION: %s\n", gl_version);
4229         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4230         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4231
4232         VID_CheckExtensions();
4233
4234         // LordHavoc: report supported extensions
4235         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4236
4237         // clear to black (loading plaque will be seen over this)
4238         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4239 }
4240
4241 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4242 {
4243         int i;
4244         mplane_t *p;
4245         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4246         {
4247                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4248                 if (i == 4)
4249                         continue;
4250                 p = r_refdef.view.frustum + i;
4251                 switch(p->signbits)
4252                 {
4253                 default:
4254                 case 0:
4255                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4256                                 return true;
4257                         break;
4258                 case 1:
4259                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4260                                 return true;
4261                         break;
4262                 case 2:
4263                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4264                                 return true;
4265                         break;
4266                 case 3:
4267                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4268                                 return true;
4269                         break;
4270                 case 4:
4271                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4272                                 return true;
4273                         break;
4274                 case 5:
4275                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4276                                 return true;
4277                         break;
4278                 case 6:
4279                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4280                                 return true;
4281                         break;
4282                 case 7:
4283                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4284                                 return true;
4285                         break;
4286                 }
4287         }
4288         return false;
4289 }
4290
4291 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4292 {
4293         int i;
4294         const mplane_t *p;
4295         for (i = 0;i < numplanes;i++)
4296         {
4297                 p = planes + i;
4298                 switch(p->signbits)
4299                 {
4300                 default:
4301                 case 0:
4302                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4303                                 return true;
4304                         break;
4305                 case 1:
4306                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4307                                 return true;
4308                         break;
4309                 case 2:
4310                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4311                                 return true;
4312                         break;
4313                 case 3:
4314                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4315                                 return true;
4316                         break;
4317                 case 4:
4318                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4319                                 return true;
4320                         break;
4321                 case 5:
4322                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4323                                 return true;
4324                         break;
4325                 case 6:
4326                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4327                                 return true;
4328                         break;
4329                 case 7:
4330                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4331                                 return true;
4332                         break;
4333                 }
4334         }
4335         return false;
4336 }
4337
4338 //==================================================================================
4339
4340 // LordHavoc: this stores temporary data used within the same frame
4341
4342 typedef struct r_framedata_mem_s
4343 {
4344         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4345         size_t size; // how much usable space
4346         size_t current; // how much space in use
4347         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4348         size_t wantedsize; // how much space was allocated
4349         unsigned char *data; // start of real data (16byte aligned)
4350 }
4351 r_framedata_mem_t;
4352
4353 static r_framedata_mem_t *r_framedata_mem;
4354
4355 void R_FrameData_Reset(void)
4356 {
4357         while (r_framedata_mem)
4358         {
4359                 r_framedata_mem_t *next = r_framedata_mem->purge;
4360                 Mem_Free(r_framedata_mem);
4361                 r_framedata_mem = next;
4362         }
4363 }
4364
4365 void R_FrameData_Resize(void)
4366 {
4367         size_t wantedsize;
4368         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4369         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4370         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4371         {
4372                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4373                 newmem->wantedsize = wantedsize;
4374                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4375                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4376                 newmem->current = 0;
4377                 newmem->mark = 0;
4378                 newmem->purge = r_framedata_mem;
4379                 r_framedata_mem = newmem;
4380         }
4381 }
4382
4383 void R_FrameData_NewFrame(void)
4384 {
4385         R_FrameData_Resize();
4386         if (!r_framedata_mem)
4387                 return;
4388         // if we ran out of space on the last frame, free the old memory now
4389         while (r_framedata_mem->purge)
4390         {
4391                 // repeatedly remove the second item in the list, leaving only head
4392                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4393                 Mem_Free(r_framedata_mem->purge);
4394                 r_framedata_mem->purge = next;
4395         }
4396         // reset the current mem pointer
4397         r_framedata_mem->current = 0;
4398         r_framedata_mem->mark = 0;
4399 }
4400
4401 void *R_FrameData_Alloc(size_t size)
4402 {
4403         void *data;
4404
4405         // align to 16 byte boundary - the data pointer is already aligned, so we
4406         // only need to ensure the size of every allocation is also aligned
4407         size = (size + 15) & ~15;
4408
4409         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4410         {
4411                 // emergency - we ran out of space, allocate more memory
4412                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4413                 R_FrameData_Resize();
4414         }
4415
4416         data = r_framedata_mem->data + r_framedata_mem->current;
4417         r_framedata_mem->current += size;
4418
4419         // count the usage for stats
4420         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4421         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4422
4423         return (void *)data;
4424 }
4425
4426 void *R_FrameData_Store(size_t size, void *data)
4427 {
4428         void *d = R_FrameData_Alloc(size);
4429         if (d && data)
4430                 memcpy(d, data, size);
4431         return d;
4432 }
4433
4434 void R_FrameData_SetMark(void)
4435 {
4436         if (!r_framedata_mem)
4437                 return;
4438         r_framedata_mem->mark = r_framedata_mem->current;
4439 }
4440
4441 void R_FrameData_ReturnToMark(void)
4442 {
4443         if (!r_framedata_mem)
4444                 return;
4445         r_framedata_mem->current = r_framedata_mem->mark;
4446 }
4447
4448 //==================================================================================
4449
4450 // LordHavoc: animcache originally written by Echon, rewritten since then
4451
4452 /**
4453  * Animation cache prevents re-generating mesh data for an animated model
4454  * multiple times in one frame for lighting, shadowing, reflections, etc.
4455  */
4456
4457 void R_AnimCache_Free(void)
4458 {
4459 }
4460
4461 void R_AnimCache_ClearCache(void)
4462 {
4463         int i;
4464         entity_render_t *ent;
4465
4466         for (i = 0;i < r_refdef.scene.numentities;i++)
4467         {
4468                 ent = r_refdef.scene.entities[i];
4469                 ent->animcache_vertex3f = NULL;
4470                 ent->animcache_normal3f = NULL;
4471                 ent->animcache_svector3f = NULL;
4472                 ent->animcache_tvector3f = NULL;
4473                 ent->animcache_vertexmesh = NULL;
4474                 ent->animcache_vertex3fbuffer = NULL;
4475                 ent->animcache_vertexmeshbuffer = NULL;
4476         }
4477 }
4478
4479 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4480 {
4481         int i;
4482
4483         // check if we need the meshbuffers
4484         if (!vid.useinterleavedarrays)
4485                 return;
4486
4487         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4488                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4489         // TODO: upload vertex3f buffer?
4490         if (ent->animcache_vertexmesh)
4491         {
4492                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4493                 for (i = 0;i < numvertices;i++)
4494                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4495                 if (ent->animcache_svector3f)
4496                         for (i = 0;i < numvertices;i++)
4497                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4498                 if (ent->animcache_tvector3f)
4499                         for (i = 0;i < numvertices;i++)
4500                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4501                 if (ent->animcache_normal3f)
4502                         for (i = 0;i < numvertices;i++)
4503                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4504                 // TODO: upload vertexmeshbuffer?
4505         }
4506 }
4507
4508 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4509 {
4510         dp_model_t *model = ent->model;
4511         int numvertices;
4512         // see if it's already cached this frame
4513         if (ent->animcache_vertex3f)
4514         {
4515                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4516                 if (wantnormals || wanttangents)
4517                 {
4518                         if (ent->animcache_normal3f)
4519                                 wantnormals = false;
4520                         if (ent->animcache_svector3f)
4521                                 wanttangents = false;
4522                         if (wantnormals || wanttangents)
4523                         {
4524                                 numvertices = model->surfmesh.num_vertices;
4525                                 if (wantnormals)
4526                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4527                                 if (wanttangents)
4528                                 {
4529                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4530                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531                                 }
4532                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4533                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4534                         }
4535                 }
4536         }
4537         else
4538         {
4539                 // see if this ent is worth caching
4540                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4541                         return false;
4542                 // get some memory for this entity and generate mesh data
4543                 numvertices = model->surfmesh.num_vertices;
4544                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4545                 if (wantnormals)
4546                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547                 if (wanttangents)
4548                 {
4549                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4550                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4551                 }
4552                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4553                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4554         }
4555         return true;
4556 }
4557
4558 void R_AnimCache_CacheVisibleEntities(void)
4559 {
4560         int i;
4561         qboolean wantnormals = true;
4562         qboolean wanttangents = !r_showsurfaces.integer;
4563
4564         switch(vid.renderpath)
4565         {
4566         case RENDERPATH_GL20:
4567         case RENDERPATH_D3D9:
4568         case RENDERPATH_D3D10:
4569         case RENDERPATH_D3D11:
4570         case RENDERPATH_GLES2:
4571                 break;
4572         case RENDERPATH_GL13:
4573         case RENDERPATH_GL11:
4574                 wanttangents = false;
4575                 break;
4576         case RENDERPATH_SOFT:
4577                 break;
4578         }
4579
4580         if (r_shownormals.integer)
4581                 wanttangents = wantnormals = true;
4582
4583         // TODO: thread this
4584         // NOTE: R_PrepareRTLights() also caches entities
4585
4586         for (i = 0;i < r_refdef.scene.numentities;i++)
4587                 if (r_refdef.viewcache.entityvisible[i])
4588                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4589 }
4590
4591 //==================================================================================
4592
4593 static void R_View_UpdateEntityLighting (void)
4594 {
4595         int i;
4596         entity_render_t *ent;
4597         vec3_t tempdiffusenormal, avg;
4598         vec_t f, fa, fd, fdd;
4599         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4600
4601         for (i = 0;i < r_refdef.scene.numentities;i++)
4602         {
4603                 ent = r_refdef.scene.entities[i];
4604
4605                 // skip unseen models
4606                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4607                         continue;
4608
4609                 // skip bsp models
4610                 if (ent->model && ent->model->brush.num_leafs)
4611                 {
4612                         // TODO: use modellight for r_ambient settings on world?
4613                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4614                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4615                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4616                         continue;
4617                 }
4618
4619                 // fetch the lighting from the worldmodel data
4620                 VectorClear(ent->modellight_ambient);
4621                 VectorClear(ent->modellight_diffuse);
4622                 VectorClear(tempdiffusenormal);
4623                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4624                 {
4625                         vec3_t org;
4626                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4627
4628                         // complete lightning for lit sprites
4629                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4630                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4631                         {
4632                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4633                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4634                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4635                         }
4636                         else
4637                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4638
4639                         if(ent->flags & RENDER_EQUALIZE)
4640                         {
4641                                 // first fix up ambient lighting...
4642                                 if(r_equalize_entities_minambient.value > 0)
4643                                 {
4644                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4645                                         if(fd > 0)
4646                                         {
4647                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4648                                                 if(fa < r_equalize_entities_minambient.value * fd)
4649                                                 {
4650                                                         // solve:
4651                                                         //   fa'/fd' = minambient
4652                                                         //   fa'+0.25*fd' = fa+0.25*fd
4653                                                         //   ...
4654                                                         //   fa' = fd' * minambient
4655                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4656                                                         //   ...
4657                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4658                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4659                                                         //   ...
4660                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4661                                                         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
4662                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4663                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4664                                                 }
4665                                         }
4666                                 }
4667
4668                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4669                                 {
4670                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4671                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4672                                         f = fa + 0.25 * fd;
4673                                         if(f > 0)
4674                                         {
4675                                                 // adjust brightness and saturation to target
4676                                                 avg[0] = avg[1] = avg[2] = fa / f;
4677                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4678                                                 avg[0] = avg[1] = avg[2] = fd / f;
4679                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4680                                         }
4681                                 }
4682                         }
4683                 }
4684                 else // highly rare
4685                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4686
4687                 // move the light direction into modelspace coordinates for lighting code
4688                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4689                 if(VectorLength2(ent->modellight_lightdir) == 0)
4690                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4691                 VectorNormalize(ent->modellight_lightdir);
4692         }
4693 }
4694
4695 #define MAX_LINEOFSIGHTTRACES 64
4696
4697 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4698 {
4699         int i;
4700         vec3_t boxmins, boxmaxs;
4701         vec3_t start;
4702         vec3_t end;
4703         dp_model_t *model = r_refdef.scene.worldmodel;
4704
4705         if (!model || !model->brush.TraceLineOfSight)
4706                 return true;
4707
4708         // expand the box a little
4709         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4710         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4711         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4712         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4713         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4714         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4715
4716         // return true if eye is inside enlarged box
4717         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4718                 return true;
4719
4720         // try center
4721         VectorCopy(eye, start);
4722         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4723         if (model->brush.TraceLineOfSight(model, start, end))
4724                 return true;
4725
4726         // try various random positions
4727         for (i = 0;i < numsamples;i++)
4728         {
4729                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4730                 if (model->brush.TraceLineOfSight(model, start, end))
4731                         return true;
4732         }
4733
4734         return false;
4735 }
4736
4737
4738 static void R_View_UpdateEntityVisible (void)
4739 {
4740         int i;
4741         int renderimask;
4742         int samples;
4743         entity_render_t *ent;
4744
4745         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4746                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4747                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4748                 :                                                          RENDER_EXTERIORMODEL;
4749         if (!r_drawviewmodel.integer)
4750                 renderimask |= RENDER_VIEWMODEL;
4751         if (!r_drawexteriormodel.integer)
4752                 renderimask |= RENDER_EXTERIORMODEL;
4753         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4754         {
4755                 // worldmodel can check visibility
4756                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4757                 for (i = 0;i < r_refdef.scene.numentities;i++)
4758                 {
4759                         ent = r_refdef.scene.entities[i];
4760                         if (!(ent->flags & renderimask))
4761                         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)))
4762                         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))
4763                                 r_refdef.viewcache.entityvisible[i] = true;
4764                 }
4765                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4766                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4767                 {
4768                         for (i = 0;i < r_refdef.scene.numentities;i++)
4769                         {
4770                                 ent = r_refdef.scene.entities[i];
4771                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4772                                 {
4773                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4774                                         if (samples < 0)
4775                                                 continue; // temp entities do pvs only
4776                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4777                                                 ent->last_trace_visibility = realtime;
4778                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4779                                                 r_refdef.viewcache.entityvisible[i] = 0;
4780                                 }
4781                         }
4782                 }
4783         }
4784         else
4785         {
4786                 // no worldmodel or it can't check visibility
4787                 for (i = 0;i < r_refdef.scene.numentities;i++)
4788                 {
4789                         ent = r_refdef.scene.entities[i];
4790                         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));
4791                 }
4792         }
4793 }
4794
4795 /// only used if skyrendermasked, and normally returns false
4796 int R_DrawBrushModelsSky (void)
4797 {
4798         int i, sky;
4799         entity_render_t *ent;
4800
4801         sky = false;
4802         for (i = 0;i < r_refdef.scene.numentities;i++)
4803         {
4804                 if (!r_refdef.viewcache.entityvisible[i])
4805                         continue;
4806                 ent = r_refdef.scene.entities[i];
4807                 if (!ent->model || !ent->model->DrawSky)
4808                         continue;
4809                 ent->model->DrawSky(ent);
4810                 sky = true;
4811         }
4812         return sky;
4813 }
4814
4815 static void R_DrawNoModel(entity_render_t *ent);
4816 static void R_DrawModels(void)
4817 {
4818         int i;
4819         entity_render_t *ent;
4820
4821         for (i = 0;i < r_refdef.scene.numentities;i++)
4822         {
4823                 if (!r_refdef.viewcache.entityvisible[i])
4824                         continue;
4825                 ent = r_refdef.scene.entities[i];
4826                 r_refdef.stats.entities++;
4827                 if (ent->model && ent->model->Draw != NULL)
4828                         ent->model->Draw(ent);
4829                 else
4830                         R_DrawNoModel(ent);
4831         }
4832 }
4833
4834 static void R_DrawModelsDepth(void)
4835 {
4836         int i;
4837         entity_render_t *ent;
4838
4839         for (i = 0;i < r_refdef.scene.numentities;i++)
4840         {
4841                 if (!r_refdef.viewcache.entityvisible[i])
4842                         continue;
4843                 ent = r_refdef.scene.entities[i];
4844                 if (ent->model && ent->model->DrawDepth != NULL)
4845                         ent->model->DrawDepth(ent);
4846         }
4847 }
4848
4849 static void R_DrawModelsDebug(void)
4850 {
4851         int i;
4852         entity_render_t *ent;
4853
4854         for (i = 0;i < r_refdef.scene.numentities;i++)
4855         {
4856                 if (!r_refdef.viewcache.entityvisible[i])
4857                         continue;
4858                 ent = r_refdef.scene.entities[i];
4859                 if (ent->model && ent->model->DrawDebug != NULL)
4860                         ent->model->DrawDebug(ent);
4861         }
4862 }
4863
4864 static void R_DrawModelsAddWaterPlanes(void)
4865 {
4866         int i;
4867         entity_render_t *ent;
4868
4869         for (i = 0;i < r_refdef.scene.numentities;i++)
4870         {
4871                 if (!r_refdef.viewcache.entityvisible[i])
4872                         continue;
4873                 ent = r_refdef.scene.entities[i];
4874                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4875                         ent->model->DrawAddWaterPlanes(ent);
4876         }
4877 }
4878
4879 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4880 {
4881         if (r_hdr_irisadaptation.integer)
4882         {
4883                 vec3_t ambient;
4884                 vec3_t diffuse;
4885                 vec3_t diffusenormal;
4886                 vec_t brightness;
4887                 vec_t goal;
4888                 vec_t adjust;
4889                 vec_t current;
4890                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4891                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4892                 brightness = max(0.0000001f, brightness);
4893                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4894                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4895                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4896                 current = r_hdr_irisadaptation_value.value;
4897                 if (current < goal)
4898                         current = min(current + adjust, goal);
4899                 else if (current > goal)
4900                         current = max(current - adjust, goal);
4901                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4902                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4903         }
4904         else if (r_hdr_irisadaptation_value.value != 1.0f)
4905                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4906 }
4907
4908 static void R_View_SetFrustum(const int *scissor)
4909 {
4910         int i;
4911         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4912         vec3_t forward, left, up, origin, v;
4913
4914         if(scissor)
4915         {
4916                 // flipped x coordinates (because x points left here)
4917                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4918                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4919
4920                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4921                 switch(vid.renderpath)
4922                 {
4923                         case RENDERPATH_D3D9:
4924                         case RENDERPATH_D3D10:
4925                         case RENDERPATH_D3D11:
4926                                 // non-flipped y coordinates
4927                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4928                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4929                                 break;
4930                         case RENDERPATH_SOFT:
4931                         case RENDERPATH_GL11:
4932                         case RENDERPATH_GL13:
4933                         case RENDERPATH_GL20:
4934                         case RENDERPATH_GLES2:
4935                                 // non-flipped y coordinates
4936                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4937                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4938                                 break;
4939                 }
4940         }
4941
4942         // we can't trust r_refdef.view.forward and friends in reflected scenes
4943         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4944
4945 #if 0
4946         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4947         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4948         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4949         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4950         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4951         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4952         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4953         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4954         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4955         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4956         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4957         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4958 #endif
4959
4960 #if 0
4961         zNear = r_refdef.nearclip;
4962         nudge = 1.0 - 1.0 / (1<<23);
4963         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4964         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4965         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4966         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4967         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4968         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4969         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4970         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4971 #endif
4972
4973
4974
4975 #if 0
4976         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4977         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4978         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4979         r_refdef.view.frustum[0].dist = m[15] - m[12];
4980
4981         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4982         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4983         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4984         r_refdef.view.frustum[1].dist = m[15] + m[12];
4985
4986         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4987         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4988         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4989         r_refdef.view.frustum[2].dist = m[15] - m[13];
4990
4991         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4992         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4993         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4994         r_refdef.view.frustum[3].dist = m[15] + m[13];
4995
4996         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4997         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4998         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4999         r_refdef.view.frustum[4].dist = m[15] - m[14];
5000
5001         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5002         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5003         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5004         r_refdef.view.frustum[5].dist = m[15] + m[14];
5005 #endif
5006
5007         if (r_refdef.view.useperspective)
5008         {
5009                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5010                 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]);
5011                 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]);
5012                 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]);
5013                 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]);
5014
5015                 // then the normals from the corners relative to origin
5016                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5017                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5018                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5019                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5020
5021                 // in a NORMAL view, forward cross left == up
5022                 // in a REFLECTED view, forward cross left == down
5023                 // so our cross products above need to be adjusted for a left handed coordinate system
5024                 CrossProduct(forward, left, v);
5025                 if(DotProduct(v, up) < 0)
5026                 {
5027                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5028                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5029                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5030                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5031                 }
5032
5033                 // Leaving those out was a mistake, those were in the old code, and they
5034                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5035                 // I couldn't reproduce it after adding those normalizations. --blub
5036                 VectorNormalize(r_refdef.view.frustum[0].normal);
5037                 VectorNormalize(r_refdef.view.frustum[1].normal);
5038                 VectorNormalize(r_refdef.view.frustum[2].normal);
5039                 VectorNormalize(r_refdef.view.frustum[3].normal);
5040
5041                 // make the corners absolute
5042                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5043                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5044                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5045                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5046
5047                 // one more normal
5048                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5049
5050                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5051                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5052                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5053                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5054                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5055         }
5056         else
5057         {
5058                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5059                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5060                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5061                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5062                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5063                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5064                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5065                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5066                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5067                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5068         }
5069         r_refdef.view.numfrustumplanes = 5;
5070
5071         if (r_refdef.view.useclipplane)
5072         {
5073                 r_refdef.view.numfrustumplanes = 6;
5074                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5075         }
5076
5077         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5078                 PlaneClassify(r_refdef.view.frustum + i);
5079
5080         // LordHavoc: note to all quake engine coders, Quake had a special case
5081         // for 90 degrees which assumed a square view (wrong), so I removed it,
5082         // Quake2 has it disabled as well.
5083
5084         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5085         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5086         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5087         //PlaneClassify(&frustum[0]);
5088
5089         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5090         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5091         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5092         //PlaneClassify(&frustum[1]);
5093
5094         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5095         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5096         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5097         //PlaneClassify(&frustum[2]);
5098
5099         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5100         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5101         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5102         //PlaneClassify(&frustum[3]);
5103
5104         // nearclip plane
5105         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5106         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5107         //PlaneClassify(&frustum[4]);
5108 }
5109
5110 void R_View_UpdateWithScissor(const int *myscissor)
5111 {
5112         R_Main_ResizeViewCache();
5113         R_View_SetFrustum(myscissor);
5114         R_View_WorldVisibility(r_refdef.view.useclipplane);
5115         R_View_UpdateEntityVisible();
5116         R_View_UpdateEntityLighting();
5117 }
5118
5119 void R_View_Update(void)
5120 {
5121         R_Main_ResizeViewCache();
5122         R_View_SetFrustum(NULL);
5123         R_View_WorldVisibility(r_refdef.view.useclipplane);
5124         R_View_UpdateEntityVisible();
5125         R_View_UpdateEntityLighting();
5126 }
5127
5128 float viewscalefpsadjusted = 1.0f;
5129
5130 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5131 {
5132         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5133         scale = bound(0.03125f, scale, 1.0f);
5134         *outwidth = (int)ceil(width * scale);
5135         *outheight = (int)ceil(height * scale);
5136 }
5137
5138 void R_Mesh_SetMainRenderTargets(void)
5139 {
5140         if (r_bloomstate.fbo_framebuffer)
5141                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5142         else
5143                 R_Mesh_ResetRenderTargets();
5144 }
5145
5146 void R_SetupView(qboolean allowwaterclippingplane)
5147 {
5148         const float *customclipplane = NULL;
5149         float plane[4];
5150         int scaledwidth, scaledheight;
5151         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5152         {
5153                 // LordHavoc: couldn't figure out how to make this approach the
5154                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5155                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5156                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5157                         dist = r_refdef.view.clipplane.dist;
5158                 plane[0] = r_refdef.view.clipplane.normal[0];
5159                 plane[1] = r_refdef.view.clipplane.normal[1];
5160                 plane[2] = r_refdef.view.clipplane.normal[2];
5161                 plane[3] = dist;
5162                 customclipplane = plane;
5163         }
5164
5165         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5166         if (!r_refdef.view.useperspective)
5167                 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);
5168         else if (vid.stencil && r_useinfinitefarclip.integer)
5169                 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);
5170         else
5171                 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);
5172         R_Mesh_SetMainRenderTargets();
5173         R_SetViewport(&r_refdef.view.viewport);
5174 }
5175
5176 void R_EntityMatrix(const matrix4x4_t *matrix)
5177 {
5178         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5179         {
5180                 gl_modelmatrixchanged = false;
5181                 gl_modelmatrix = *matrix;
5182                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5183                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5184                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5185                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5186                 CHECKGLERROR
5187                 switch(vid.renderpath)
5188                 {
5189                 case RENDERPATH_D3D9:
5190 #ifdef SUPPORTD3D
5191                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5192                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5193 #endif
5194                         break;
5195                 case RENDERPATH_D3D10:
5196                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5197                         break;
5198                 case RENDERPATH_D3D11:
5199                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5200                         break;
5201                 case RENDERPATH_GL13:
5202                 case RENDERPATH_GL11:
5203                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5204                         break;
5205                 case RENDERPATH_SOFT:
5206                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5207                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5208                         break;
5209                 case RENDERPATH_GL20:
5210                 case RENDERPATH_GLES2:
5211                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5212                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5213                         break;
5214                 }
5215         }
5216 }
5217
5218 void R_ResetViewRendering2D(void)
5219 {
5220         r_viewport_t viewport;
5221         DrawQ_Finish();
5222
5223         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5224         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);
5225         R_Mesh_ResetRenderTargets();
5226         R_SetViewport(&viewport);
5227         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5228         GL_Color(1, 1, 1, 1);
5229         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5230         GL_BlendFunc(GL_ONE, GL_ZERO);
5231         GL_ScissorTest(false);
5232         GL_DepthMask(false);
5233         GL_DepthRange(0, 1);
5234         GL_DepthTest(false);
5235         GL_DepthFunc(GL_LEQUAL);
5236         R_EntityMatrix(&identitymatrix);
5237         R_Mesh_ResetTextureState();
5238         GL_PolygonOffset(0, 0);
5239         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5240         switch(vid.renderpath)
5241         {
5242         case RENDERPATH_GL11:
5243         case RENDERPATH_GL13:
5244         case RENDERPATH_GL20:
5245         case RENDERPATH_GLES2:
5246                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5247                 break;
5248         case RENDERPATH_D3D9:
5249         case RENDERPATH_D3D10:
5250         case RENDERPATH_D3D11:
5251         case RENDERPATH_SOFT:
5252                 break;
5253         }
5254         GL_CullFace(GL_NONE);
5255 }
5256
5257 void R_ResetViewRendering3D(void)
5258 {
5259         DrawQ_Finish();
5260
5261         R_SetupView(true);
5262         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5263         GL_Color(1, 1, 1, 1);
5264         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5265         GL_BlendFunc(GL_ONE, GL_ZERO);
5266         GL_ScissorTest(true);
5267         GL_DepthMask(true);
5268         GL_DepthRange(0, 1);
5269         GL_DepthTest(true);
5270         GL_DepthFunc(GL_LEQUAL);
5271         R_EntityMatrix(&identitymatrix);
5272         R_Mesh_ResetTextureState();
5273         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5274         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5275         switch(vid.renderpath)
5276         {
5277         case RENDERPATH_GL11:
5278         case RENDERPATH_GL13:
5279         case RENDERPATH_GL20:
5280         case RENDERPATH_GLES2:
5281                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5282                 break;
5283         case RENDERPATH_D3D9:
5284         case RENDERPATH_D3D10:
5285         case RENDERPATH_D3D11:
5286         case RENDERPATH_SOFT:
5287                 break;
5288         }
5289         GL_CullFace(r_refdef.view.cullface_back);
5290 }
5291
5292 /*
5293 ================
5294 R_RenderView_UpdateViewVectors
5295 ================
5296 */
5297 static void R_RenderView_UpdateViewVectors(void)
5298 {
5299         // break apart the view matrix into vectors for various purposes
5300         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5301         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5302         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5303         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5304         // make an inverted copy of the view matrix for tracking sprites
5305         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5306 }
5307
5308 void R_RenderScene(void);
5309 void R_RenderWaterPlanes(void);
5310
5311 static void R_Water_StartFrame(void)
5312 {
5313         int i;
5314         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5315         r_waterstate_waterplane_t *p;
5316
5317         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5318                 return;
5319
5320         switch(vid.renderpath)
5321         {
5322         case RENDERPATH_GL20:
5323         case RENDERPATH_D3D9:
5324         case RENDERPATH_D3D10:
5325         case RENDERPATH_D3D11:
5326         case RENDERPATH_SOFT:
5327         case RENDERPATH_GLES2:
5328                 break;
5329         case RENDERPATH_GL13:
5330         case RENDERPATH_GL11:
5331                 return;
5332         }
5333
5334         // set waterwidth and waterheight to the water resolution that will be
5335         // used (often less than the screen resolution for faster rendering)
5336         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5337         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5338
5339         // calculate desired texture sizes
5340         // can't use water if the card does not support the texture size
5341         if (!r_water.integer || r_showsurfaces.integer)
5342                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5343         else if (vid.support.arb_texture_non_power_of_two)
5344         {
5345                 texturewidth = waterwidth;
5346                 textureheight = waterheight;
5347                 camerawidth = waterwidth;
5348                 cameraheight = waterheight;
5349         }
5350         else
5351         {
5352                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5353                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5354                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5355                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5356         }
5357
5358         // allocate textures as needed
5359         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5360         {
5361                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5362                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5363                 {
5364                         if (p->texture_refraction)
5365                                 R_FreeTexture(p->texture_refraction);
5366                         p->texture_refraction = NULL;
5367                         if (p->texture_reflection)
5368                                 R_FreeTexture(p->texture_reflection);
5369                         p->texture_reflection = NULL;
5370                         if (p->texture_camera)
5371                                 R_FreeTexture(p->texture_camera);
5372                         p->texture_camera = NULL;
5373                 }
5374                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5375                 r_waterstate.texturewidth = texturewidth;
5376                 r_waterstate.textureheight = textureheight;
5377                 r_waterstate.camerawidth = camerawidth;
5378                 r_waterstate.cameraheight = cameraheight;
5379         }
5380
5381         if (r_waterstate.texturewidth)
5382         {
5383                 r_waterstate.enabled = true;
5384
5385                 // when doing a reduced render (HDR) we want to use a smaller area
5386                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5387                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5388
5389                 // set up variables that will be used in shader setup
5390                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5391                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5392                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5393                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5394         }
5395
5396         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5397         r_waterstate.numwaterplanes = 0;
5398 }
5399
5400 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5401 {
5402         int triangleindex, planeindex;
5403         const int *e;
5404         vec3_t vert[3];
5405         vec3_t normal;
5406         vec3_t center;
5407         mplane_t plane;
5408         r_waterstate_waterplane_t *p;
5409         texture_t *t = R_GetCurrentTexture(surface->texture);
5410
5411         // just use the first triangle with a valid normal for any decisions
5412         VectorClear(normal);
5413         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5414         {
5415                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5416                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5417                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5418                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5419                 if (VectorLength2(normal) >= 0.001)
5420                         break;
5421         }
5422
5423         VectorCopy(normal, plane.normal);
5424         VectorNormalize(plane.normal);
5425         plane.dist = DotProduct(vert[0], plane.normal);
5426         PlaneClassify(&plane);
5427         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5428         {
5429                 // skip backfaces (except if nocullface is set)
5430                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5431                         return;
5432                 VectorNegate(plane.normal, plane.normal);
5433                 plane.dist *= -1;
5434                 PlaneClassify(&plane);
5435         }
5436
5437
5438         // find a matching plane if there is one
5439         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5440                 if(p->camera_entity == t->camera_entity)
5441                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5442                                 break;
5443         if (planeindex >= r_waterstate.maxwaterplanes)
5444                 return; // nothing we can do, out of planes
5445
5446         // if this triangle does not fit any known plane rendered this frame, add one
5447         if (planeindex >= r_waterstate.numwaterplanes)
5448         {
5449                 // store the new plane
5450                 r_waterstate.numwaterplanes++;
5451                 p->plane = plane;
5452                 // clear materialflags and pvs
5453                 p->materialflags = 0;
5454                 p->pvsvalid = false;
5455                 p->camera_entity = t->camera_entity;
5456                 VectorCopy(surface->mins, p->mins);
5457                 VectorCopy(surface->maxs, p->maxs);
5458         }
5459         else
5460         {
5461                 // merge mins/maxs
5462                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5463                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5464                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5465                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5466                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5467                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5468         }
5469         // merge this surface's materialflags into the waterplane
5470         p->materialflags |= t->currentmaterialflags;
5471         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5472         {
5473                 // merge this surface's PVS into the waterplane
5474                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5475                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5476                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5477                 {
5478                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5479                         p->pvsvalid = true;
5480                 }
5481         }
5482 }
5483
5484 static void R_Water_ProcessPlanes(void)
5485 {
5486         int myscissor[4];
5487         r_refdef_view_t originalview;
5488         r_refdef_view_t myview;
5489         int planeindex;
5490         r_waterstate_waterplane_t *p;
5491         vec3_t visorigin;
5492
5493         originalview = r_refdef.view;
5494
5495         // make sure enough textures are allocated
5496         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5497         {
5498                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5499                 {
5500                         if (!p->texture_refraction)
5501                                 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);
5502                         if (!p->texture_refraction)
5503                                 goto error;
5504                 }
5505                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5506                 {
5507                         if (!p->texture_camera)
5508                                 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);
5509                         if (!p->texture_camera)
5510                                 goto error;
5511                 }
5512
5513                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5514                 {
5515                         if (!p->texture_reflection)
5516                                 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);
5517                         if (!p->texture_reflection)
5518                                 goto error;
5519                 }
5520         }
5521
5522         // render views
5523         r_refdef.view = originalview;
5524         r_refdef.view.showdebug = false;
5525         r_refdef.view.width = r_waterstate.waterwidth;
5526         r_refdef.view.height = r_waterstate.waterheight;
5527         r_refdef.view.useclipplane = true;
5528         myview = r_refdef.view;
5529         r_waterstate.renderingscene = true;
5530         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5531         {
5532                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5533                 {
5534                         r_refdef.view = myview;
5535                         if(r_water_scissormode.integer)
5536                         {
5537                                 R_SetupView(true);
5538                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5539                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5540                         }
5541
5542                         // render reflected scene and copy into texture
5543                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5544                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5545                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5546                         r_refdef.view.clipplane = p->plane;
5547
5548                         // reverse the cullface settings for this render
5549                         r_refdef.view.cullface_front = GL_FRONT;
5550                         r_refdef.view.cullface_back = GL_BACK;
5551                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5552                         {
5553                                 r_refdef.view.usecustompvs = true;
5554                                 if (p->pvsvalid)
5555                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5556                                 else
5557                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5558                         }
5559
5560                         R_ResetViewRendering3D();
5561                         R_ClearScreen(r_refdef.fogenabled);
5562                         if(r_water_scissormode.integer & 2)
5563                                 R_View_UpdateWithScissor(myscissor);
5564                         else
5565                                 R_View_Update();
5566                         if(r_water_scissormode.integer & 1)
5567                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5568                         R_RenderScene();
5569
5570                         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);
5571                 }
5572
5573                 // render the normal view scene and copy into texture
5574                 // (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)
5575                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5576                 {
5577                         r_refdef.view = myview;
5578                         if(r_water_scissormode.integer)
5579                         {
5580                                 R_SetupView(true);
5581                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5582                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5583                         }
5584
5585                         r_waterstate.renderingrefraction = true;
5586
5587                         r_refdef.view.clipplane = p->plane;
5588                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5589                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5590
5591                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5592                         {
5593                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5594                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5595                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5596                                 R_RenderView_UpdateViewVectors();
5597                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5598                                 {
5599                                         r_refdef.view.usecustompvs = true;
5600                                         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);
5601                                 }
5602                         }
5603
5604                         PlaneClassify(&r_refdef.view.clipplane);
5605
5606                         R_ResetViewRendering3D();
5607                         R_ClearScreen(r_refdef.fogenabled);
5608                         if(r_water_scissormode.integer & 2)
5609                                 R_View_UpdateWithScissor(myscissor);
5610                         else
5611                                 R_View_Update();
5612                         if(r_water_scissormode.integer & 1)
5613                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5614                         R_RenderScene();
5615
5616                         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);
5617                         r_waterstate.renderingrefraction = false;
5618                 }
5619                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5620                 {
5621                         r_refdef.view = myview;
5622
5623                         r_refdef.view.clipplane = p->plane;
5624                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5625                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5626
5627                         r_refdef.view.width = r_waterstate.camerawidth;
5628                         r_refdef.view.height = r_waterstate.cameraheight;
5629                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5630                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5631
5632                         if(p->camera_entity)
5633                         {
5634                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5635                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5636                         }
5637
5638                         // note: all of the view is used for displaying... so
5639                         // there is no use in scissoring
5640
5641                         // reverse the cullface settings for this render
5642                         r_refdef.view.cullface_front = GL_FRONT;
5643                         r_refdef.view.cullface_back = GL_BACK;
5644                         // also reverse the view matrix
5645                         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
5646                         R_RenderView_UpdateViewVectors();
5647                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5648                         {
5649                                 r_refdef.view.usecustompvs = true;
5650                                 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);
5651                         }
5652                         
5653                         // camera needs no clipplane
5654                         r_refdef.view.useclipplane = false;
5655
5656                         PlaneClassify(&r_refdef.view.clipplane);
5657
5658                         R_ResetViewRendering3D();
5659                         R_ClearScreen(r_refdef.fogenabled);
5660                         R_View_Update();
5661                         R_RenderScene();
5662
5663                         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);
5664                         r_waterstate.renderingrefraction = false;
5665                 }
5666
5667         }
5668         r_waterstate.renderingscene = false;
5669         r_refdef.view = originalview;
5670         R_ResetViewRendering3D();
5671         R_ClearScreen(r_refdef.fogenabled);
5672         R_View_Update();
5673         return;
5674 error:
5675         r_refdef.view = originalview;
5676         r_waterstate.renderingscene = false;
5677         Cvar_SetValueQuick(&r_water, 0);
5678         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5679         return;
5680 }
5681
5682 void R_Bloom_StartFrame(void)
5683 {
5684         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5685         int viewwidth, viewheight;
5686         textype_t textype;
5687
5688         if (r_viewscale_fpsscaling.integer)
5689         {
5690                 double actualframetime;
5691                 double targetframetime;
5692                 double adjust;
5693                 actualframetime = r_refdef.lastdrawscreentime;
5694                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5695                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5696                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5697                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5698                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5699                 viewscalefpsadjusted += adjust;
5700                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5701         }
5702         else
5703                 viewscalefpsadjusted = 1.0f;
5704
5705         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5706
5707         switch(vid.renderpath)
5708         {
5709         case RENDERPATH_GL20:
5710         case RENDERPATH_D3D9:
5711         case RENDERPATH_D3D10:
5712         case RENDERPATH_D3D11:
5713         case RENDERPATH_SOFT:
5714         case RENDERPATH_GLES2:
5715                 break;
5716         case RENDERPATH_GL13:
5717         case RENDERPATH_GL11:
5718                 return;
5719         }
5720
5721         // set bloomwidth and bloomheight to the bloom resolution that will be
5722         // used (often less than the screen resolution for faster rendering)
5723         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5724         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5725         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5726         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5727         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5728
5729         // calculate desired texture sizes
5730         if (vid.support.arb_texture_non_power_of_two)
5731         {
5732                 screentexturewidth = vid.width;
5733                 screentextureheight = vid.height;
5734                 bloomtexturewidth = r_bloomstate.bloomwidth;
5735                 bloomtextureheight = r_bloomstate.bloomheight;
5736         }
5737         else
5738         {
5739                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5740                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5741                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5742                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5743         }
5744
5745         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))
5746         {
5747                 Cvar_SetValueQuick(&r_hdr, 0);
5748                 Cvar_SetValueQuick(&r_bloom, 0);
5749                 Cvar_SetValueQuick(&r_motionblur, 0);
5750                 Cvar_SetValueQuick(&r_damageblur, 0);
5751         }
5752
5753         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)
5754                 screentexturewidth = screentextureheight = 0;
5755         if (!r_hdr.integer && !r_bloom.integer)
5756                 bloomtexturewidth = bloomtextureheight = 0;
5757
5758         textype = TEXTYPE_COLORBUFFER;
5759         switch (vid.renderpath)
5760         {
5761         case RENDERPATH_GL20:
5762         case RENDERPATH_GLES2:
5763                 if (vid.support.ext_framebuffer_object)
5764                 {
5765                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5766                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5767                 }
5768                 break;
5769         case RENDERPATH_D3D9:
5770         case RENDERPATH_D3D10:
5771         case RENDERPATH_D3D11:
5772         case RENDERPATH_SOFT:
5773         case RENDERPATH_GL13:
5774         case RENDERPATH_GL11:
5775                 break;
5776         }
5777
5778         // allocate textures as needed
5779         if (r_bloomstate.screentexturewidth != screentexturewidth
5780          || r_bloomstate.screentextureheight != screentextureheight
5781          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5782          || r_bloomstate.bloomtextureheight != bloomtextureheight
5783          || r_bloomstate.texturetype != textype
5784          || r_bloomstate.viewfbo != r_viewfbo.integer)
5785         {
5786                 if (r_bloomstate.texture_bloom)
5787                         R_FreeTexture(r_bloomstate.texture_bloom);
5788                 r_bloomstate.texture_bloom = NULL;
5789                 if (r_bloomstate.texture_screen)
5790                         R_FreeTexture(r_bloomstate.texture_screen);
5791                 r_bloomstate.texture_screen = NULL;
5792                 if (r_bloomstate.fbo_framebuffer)
5793                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5794                 r_bloomstate.fbo_framebuffer = 0;
5795                 if (r_bloomstate.texture_framebuffercolor)
5796                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5797                 r_bloomstate.texture_framebuffercolor = NULL;
5798                 if (r_bloomstate.texture_framebufferdepth)
5799                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5800                 r_bloomstate.texture_framebufferdepth = NULL;
5801                 r_bloomstate.screentexturewidth = screentexturewidth;
5802                 r_bloomstate.screentextureheight = screentextureheight;
5803                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5804                         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);
5805                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5806                 {
5807                         // FIXME: choose depth bits based on a cvar
5808                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5809                         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);
5810                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5811                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5812                         // render depth into one texture and normalmap into the other
5813                         if (qglDrawBuffer)
5814                         {
5815                                 int status;
5816                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5817                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5818                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5819                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5820                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5821                         }
5822                 }
5823                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5824                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5825                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5826                         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);
5827                 r_bloomstate.viewfbo = r_viewfbo.integer;
5828                 r_bloomstate.texturetype = textype;
5829         }
5830
5831         // when doing a reduced render (HDR) we want to use a smaller area
5832         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5833         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5834         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5835         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5836         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5837
5838         // set up a texcoord array for the full resolution screen image
5839         // (we have to keep this around to copy back during final render)
5840         r_bloomstate.screentexcoord2f[0] = 0;
5841         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5842         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5843         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5844         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5845         r_bloomstate.screentexcoord2f[5] = 0;
5846         r_bloomstate.screentexcoord2f[6] = 0;
5847         r_bloomstate.screentexcoord2f[7] = 0;
5848
5849         // set up a texcoord array for the reduced resolution bloom image
5850         // (which will be additive blended over the screen image)
5851         r_bloomstate.bloomtexcoord2f[0] = 0;
5852         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5853         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5854         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5855         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5856         r_bloomstate.bloomtexcoord2f[5] = 0;
5857         r_bloomstate.bloomtexcoord2f[6] = 0;
5858         r_bloomstate.bloomtexcoord2f[7] = 0;
5859
5860         switch(vid.renderpath)
5861         {
5862         case RENDERPATH_GL11:
5863         case RENDERPATH_GL13:
5864         case RENDERPATH_GL20:
5865         case RENDERPATH_SOFT:
5866         case RENDERPATH_GLES2:
5867                 break;
5868         case RENDERPATH_D3D9:
5869         case RENDERPATH_D3D10:
5870         case RENDERPATH_D3D11:
5871                 {
5872                         int i;
5873                         for (i = 0;i < 4;i++)
5874                         {
5875                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5876                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5877                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5878                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5879                         }
5880                 }
5881                 break;
5882         }
5883
5884         if (r_hdr.integer || r_bloom.integer)
5885         {
5886                 r_bloomstate.enabled = true;
5887                 r_bloomstate.hdr = r_hdr.integer != 0;
5888         }
5889
5890         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);
5891
5892         if (r_bloomstate.fbo_framebuffer)
5893                 r_refdef.view.clear = true;
5894 }
5895
5896 void R_Bloom_CopyBloomTexture(float colorscale)
5897 {
5898         r_refdef.stats.bloom++;
5899
5900         // scale down screen texture to the bloom texture size
5901         CHECKGLERROR
5902         R_Mesh_SetMainRenderTargets();
5903         R_SetViewport(&r_bloomstate.viewport);
5904         GL_BlendFunc(GL_ONE, GL_ZERO);
5905         GL_Color(colorscale, colorscale, colorscale, 1);
5906         // 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...
5907         switch(vid.renderpath)
5908         {
5909         case RENDERPATH_GL11:
5910         case RENDERPATH_GL13:
5911         case RENDERPATH_GL20:
5912         case RENDERPATH_SOFT:
5913         case RENDERPATH_GLES2:
5914                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5915                 break;
5916         case RENDERPATH_D3D9:
5917         case RENDERPATH_D3D10:
5918         case RENDERPATH_D3D11:
5919                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5920                 break;
5921         }
5922         // TODO: do boxfilter scale-down in shader?
5923         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5924         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5925         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5926
5927         // we now have a bloom image in the framebuffer
5928         // copy it into the bloom image texture for later processing
5929         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);
5930         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5931 }
5932
5933 void R_Bloom_CopyHDRTexture(void)
5934 {
5935         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);
5936         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5937 }
5938
5939 void R_Bloom_MakeTexture(void)
5940 {
5941         int x, range, dir;
5942         float xoffset, yoffset, r, brighten;
5943
5944         r_refdef.stats.bloom++;
5945
5946         R_ResetViewRendering2D();
5947
5948         // we have a bloom image in the framebuffer
5949         CHECKGLERROR
5950         R_SetViewport(&r_bloomstate.viewport);
5951
5952         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5953         {
5954                 x *= 2;
5955                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5956                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5957                 GL_Color(r,r,r,1);
5958                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5959                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5960                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5961                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5962
5963                 // copy the vertically blurred bloom view to a texture
5964                 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);
5965                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5966         }
5967
5968         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5969         brighten = r_bloom_brighten.value;
5970         if (r_hdr.integer)
5971                 brighten *= r_hdr_range.value;
5972         brighten = sqrt(brighten);
5973         if(range >= 1)
5974                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5975         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5976
5977         for (dir = 0;dir < 2;dir++)
5978         {
5979                 // blend on at multiple vertical offsets to achieve a vertical blur
5980                 // TODO: do offset blends using GLSL
5981                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5982                 GL_BlendFunc(GL_ONE, GL_ZERO);
5983                 for (x = -range;x <= range;x++)
5984                 {
5985                         if (!dir){xoffset = 0;yoffset = x;}
5986                         else {xoffset = x;yoffset = 0;}
5987                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5988                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5989                         // compute a texcoord array with the specified x and y offset
5990                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5991                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5992                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5993                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5994                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5995                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5996                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5997                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5998                         // this r value looks like a 'dot' particle, fading sharply to
5999                         // black at the edges
6000                         // (probably not realistic but looks good enough)
6001                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6002                         //r = brighten/(range*2+1);
6003                         r = brighten / (range * 2 + 1);
6004                         if(range >= 1)
6005                                 r *= (1 - x*x/(float)(range*range));
6006                         GL_Color(r, r, r, 1);
6007                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6008                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6009                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6010                         GL_BlendFunc(GL_ONE, GL_ONE);
6011                 }
6012
6013                 // copy the vertically blurred bloom view to a texture
6014                 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);
6015                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6016         }
6017 }
6018
6019 void R_HDR_RenderBloomTexture(void)
6020 {
6021         int oldwidth, oldheight;
6022         float oldcolorscale;
6023         qboolean oldwaterstate;
6024
6025         oldwaterstate = r_waterstate.enabled;
6026         oldcolorscale = r_refdef.view.colorscale;
6027         oldwidth = r_refdef.view.width;
6028         oldheight = r_refdef.view.height;
6029         r_refdef.view.width = r_bloomstate.bloomwidth;
6030         r_refdef.view.height = r_bloomstate.bloomheight;
6031
6032         if(r_hdr.integer < 2)
6033                 r_waterstate.enabled = false;
6034
6035         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6036         // TODO: add exposure compensation features
6037         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6038
6039         r_refdef.view.showdebug = false;
6040         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6041
6042         R_ResetViewRendering3D();
6043
6044         R_ClearScreen(r_refdef.fogenabled);
6045         if (r_timereport_active)
6046                 R_TimeReport("HDRclear");
6047
6048         R_View_Update();
6049         if (r_timereport_active)
6050                 R_TimeReport("visibility");
6051
6052         // only do secondary renders with HDR if r_hdr is 2 or higher
6053         r_waterstate.numwaterplanes = 0;
6054         if (r_waterstate.enabled)
6055                 R_RenderWaterPlanes();
6056
6057         r_refdef.view.showdebug = true;
6058         R_RenderScene();
6059         r_waterstate.numwaterplanes = 0;
6060
6061         R_ResetViewRendering2D();
6062
6063         R_Bloom_CopyHDRTexture();
6064         R_Bloom_MakeTexture();
6065
6066         // restore the view settings
6067         r_waterstate.enabled = oldwaterstate;
6068         r_refdef.view.width = oldwidth;
6069         r_refdef.view.height = oldheight;
6070         r_refdef.view.colorscale = oldcolorscale;
6071
6072         R_ResetViewRendering3D();
6073
6074         R_ClearScreen(r_refdef.fogenabled);
6075         if (r_timereport_active)
6076                 R_TimeReport("viewclear");
6077 }
6078
6079 static void R_BlendView(void)
6080 {
6081         unsigned int permutation;
6082         float uservecs[4][4];
6083
6084         switch (vid.renderpath)
6085         {
6086         case RENDERPATH_GL20:
6087         case RENDERPATH_D3D9:
6088         case RENDERPATH_D3D10:
6089         case RENDERPATH_D3D11:
6090         case RENDERPATH_SOFT:
6091         case RENDERPATH_GLES2:
6092                 permutation =
6093                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6094                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6095                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6096                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6097                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6098
6099                 if (r_bloomstate.texture_screen)
6100                 {
6101                         // make sure the buffer is available
6102                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6103
6104                         R_ResetViewRendering2D();
6105                         R_Mesh_SetMainRenderTargets();
6106
6107                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6108                         {
6109                                 // declare variables
6110                                 float speed;
6111                                 static float avgspeed;
6112
6113                                 speed = VectorLength(cl.movement_velocity);
6114
6115                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6116                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6117
6118                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6119                                 speed = bound(0, speed, 1);
6120                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6121
6122                                 // calculate values into a standard alpha
6123                                 cl.motionbluralpha = 1 - exp(-
6124                                                 (
6125                                                  (r_motionblur.value * speed / 80)
6126                                                  +
6127                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6128                                                 )
6129                                                 /
6130                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6131                                            );
6132
6133                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6134                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6135                                 // apply the blur
6136                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6137                                 {
6138                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6139                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6140                                         switch(vid.renderpath)
6141                                         {
6142                                         case RENDERPATH_GL11:
6143                                         case RENDERPATH_GL13:
6144                                         case RENDERPATH_GL20:
6145                                         case RENDERPATH_SOFT:
6146                                         case RENDERPATH_GLES2:
6147                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6148                                                 break;
6149                                         case RENDERPATH_D3D9:
6150                                         case RENDERPATH_D3D10:
6151                                         case RENDERPATH_D3D11:
6152                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6153                                                 break;
6154                                         }
6155                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6156                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6157                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6158                                 }
6159                         }
6160
6161                         // copy view into the screen texture
6162                         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);
6163                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6164                 }
6165                 else if (!r_bloomstate.texture_bloom)
6166                 {
6167                         // we may still have to do view tint...
6168                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6169                         {
6170                                 // apply a color tint to the whole view
6171                                 R_ResetViewRendering2D();
6172                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6173                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6174                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6175                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6176                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6177                         }
6178                         break; // no screen processing, no bloom, skip it
6179                 }
6180
6181                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6182                 {
6183                         // render simple bloom effect
6184                         // copy the screen and shrink it and darken it for the bloom process
6185                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6186                         // make the bloom texture
6187                         R_Bloom_MakeTexture();
6188                 }
6189
6190 #if _MSC_VER >= 1400
6191 #define sscanf sscanf_s
6192 #endif
6193                 memset(uservecs, 0, sizeof(uservecs));
6194                 if (r_glsl_postprocess_uservec1_enable.integer)
6195                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6196                 if (r_glsl_postprocess_uservec2_enable.integer)
6197                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6198                 if (r_glsl_postprocess_uservec3_enable.integer)
6199                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6200                 if (r_glsl_postprocess_uservec4_enable.integer)
6201                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6202
6203                 R_ResetViewRendering2D();
6204                 GL_Color(1, 1, 1, 1);
6205                 GL_BlendFunc(GL_ONE, GL_ZERO);
6206
6207                 switch(vid.renderpath)
6208                 {
6209                 case RENDERPATH_GL20:
6210                 case RENDERPATH_GLES2:
6211                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6212                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6213                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6214                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6215                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6216                         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]);
6217                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6218                         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]);
6219                         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]);
6220                         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]);
6221                         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]);
6222                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6223                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6224                         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);
6225                         break;
6226                 case RENDERPATH_D3D9:
6227 #ifdef SUPPORTD3D
6228                         // 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...
6229                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6230                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6231                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6232                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6233                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6234                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6235                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6236                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6237                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6238                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6239                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6240                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6241                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6242                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6243 #endif
6244                         break;
6245                 case RENDERPATH_D3D10:
6246                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6247                         break;
6248                 case RENDERPATH_D3D11:
6249                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6250                         break;
6251                 case RENDERPATH_SOFT:
6252                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6253                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6254                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6255                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6256                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6257                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6258                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6259                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6260                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6261                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6262                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6263                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6264                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6265                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6266                         break;
6267                 default:
6268                         break;
6269                 }
6270                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6271                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6272                 break;
6273         case RENDERPATH_GL13:
6274         case RENDERPATH_GL11:
6275                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6276                 {
6277                         // apply a color tint to the whole view
6278                         R_ResetViewRendering2D();
6279                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6280                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6281                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6282                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6283                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6284                 }
6285                 break;
6286         }
6287 }
6288
6289 matrix4x4_t r_waterscrollmatrix;
6290
6291 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6292 {
6293         if (r_refdef.fog_density)
6294         {
6295                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6296                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6297                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6298
6299                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6300                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6301                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6302                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6303
6304                 {
6305                         vec3_t fogvec;
6306                         VectorCopy(r_refdef.fogcolor, fogvec);
6307                         //   color.rgb *= ContrastBoost * SceneBrightness;
6308                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6309                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6310                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6311                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6312                 }
6313         }
6314 }
6315
6316 void R_UpdateVariables(void)
6317 {
6318         R_Textures_Frame();
6319
6320         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6321
6322         r_refdef.farclip = r_farclip_base.value;
6323         if (r_refdef.scene.worldmodel)
6324                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6325         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6326
6327         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6328                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6329         r_refdef.polygonfactor = 0;
6330         r_refdef.polygonoffset = 0;
6331         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6332         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6333
6334         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6335         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6336         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6337         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6338         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6339         if (FAKELIGHT_ENABLED)
6340         {
6341                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6342         }
6343         if (r_showsurfaces.integer)
6344         {
6345                 r_refdef.scene.rtworld = false;
6346                 r_refdef.scene.rtworldshadows = false;
6347                 r_refdef.scene.rtdlight = false;
6348                 r_refdef.scene.rtdlightshadows = false;
6349                 r_refdef.lightmapintensity = 0;
6350         }
6351
6352         if (gamemode == GAME_NEHAHRA)
6353         {
6354                 if (gl_fogenable.integer)
6355                 {
6356                         r_refdef.oldgl_fogenable = true;
6357                         r_refdef.fog_density = gl_fogdensity.value;
6358                         r_refdef.fog_red = gl_fogred.value;
6359                         r_refdef.fog_green = gl_foggreen.value;
6360                         r_refdef.fog_blue = gl_fogblue.value;
6361                         r_refdef.fog_alpha = 1;
6362                         r_refdef.fog_start = 0;
6363                         r_refdef.fog_end = gl_skyclip.value;
6364                         r_refdef.fog_height = 1<<30;
6365                         r_refdef.fog_fadedepth = 128;
6366                 }
6367                 else if (r_refdef.oldgl_fogenable)
6368                 {
6369                         r_refdef.oldgl_fogenable = false;
6370                         r_refdef.fog_density = 0;
6371                         r_refdef.fog_red = 0;
6372                         r_refdef.fog_green = 0;
6373                         r_refdef.fog_blue = 0;
6374                         r_refdef.fog_alpha = 0;
6375                         r_refdef.fog_start = 0;
6376                         r_refdef.fog_end = 0;
6377                         r_refdef.fog_height = 1<<30;
6378                         r_refdef.fog_fadedepth = 128;
6379                 }
6380         }
6381
6382         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6383         r_refdef.fog_start = max(0, r_refdef.fog_start);
6384         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6385
6386         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6387
6388         if (r_refdef.fog_density && r_drawfog.integer)
6389         {
6390                 r_refdef.fogenabled = true;
6391                 // this is the point where the fog reaches 0.9986 alpha, which we
6392                 // consider a good enough cutoff point for the texture
6393                 // (0.9986 * 256 == 255.6)
6394                 if (r_fog_exp2.integer)
6395                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6396                 else
6397                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6398                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6399                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6400                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6401                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6402                         R_BuildFogHeightTexture();
6403                 // fog color was already set
6404                 // update the fog texture
6405                 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)
6406                         R_BuildFogTexture();
6407                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6408                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6409         }
6410         else
6411                 r_refdef.fogenabled = false;
6412
6413         switch(vid.renderpath)
6414         {
6415         case RENDERPATH_GL20:
6416         case RENDERPATH_D3D9:
6417         case RENDERPATH_D3D10:
6418         case RENDERPATH_D3D11:
6419         case RENDERPATH_SOFT:
6420         case RENDERPATH_GLES2:
6421                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6422                 {
6423                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6424                         {
6425                                 // build GLSL gamma texture
6426 #define RAMPWIDTH 256
6427                                 unsigned short ramp[RAMPWIDTH * 3];
6428                                 unsigned char rampbgr[RAMPWIDTH][4];
6429                                 int i;
6430
6431                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6432
6433                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6434                                 for(i = 0; i < RAMPWIDTH; ++i)
6435                                 {
6436                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6437                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6438                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6439                                         rampbgr[i][3] = 0;
6440                                 }
6441                                 if (r_texture_gammaramps)
6442                                 {
6443                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6444                                 }
6445                                 else
6446                                 {
6447                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6448                                 }
6449                         }
6450                 }
6451                 else
6452                 {
6453                         // remove GLSL gamma texture
6454                 }
6455                 break;
6456         case RENDERPATH_GL13:
6457         case RENDERPATH_GL11:
6458                 break;
6459         }
6460 }
6461
6462 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6463 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6464 /*
6465 ================
6466 R_SelectScene
6467 ================
6468 */
6469 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6470         if( scenetype != r_currentscenetype ) {
6471                 // store the old scenetype
6472                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6473                 r_currentscenetype = scenetype;
6474                 // move in the new scene
6475                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6476         }
6477 }
6478
6479 /*
6480 ================
6481 R_GetScenePointer
6482 ================
6483 */
6484 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6485 {
6486         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6487         if( scenetype == r_currentscenetype ) {
6488                 return &r_refdef.scene;
6489         } else {
6490                 return &r_scenes_store[ scenetype ];
6491         }
6492 }
6493
6494 /*
6495 ================
6496 R_RenderView
6497 ================
6498 */
6499 int dpsoftrast_test;
6500 void R_RenderView(void)
6501 {
6502         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6503
6504         dpsoftrast_test = r_test.integer;
6505
6506         if (r_timereport_active)
6507                 R_TimeReport("start");
6508         r_textureframe++; // used only by R_GetCurrentTexture
6509         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6510
6511         if(R_CompileShader_CheckStaticParms())
6512                 R_GLSL_Restart_f();
6513
6514         if (!r_drawentities.integer)
6515                 r_refdef.scene.numentities = 0;
6516
6517         R_AnimCache_ClearCache();
6518         R_FrameData_NewFrame();
6519
6520         /* adjust for stereo display */
6521         if(R_Stereo_Active())
6522         {
6523                 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);
6524                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6525         }
6526
6527         if (r_refdef.view.isoverlay)
6528         {
6529                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6530                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6531                 R_TimeReport("depthclear");
6532
6533                 r_refdef.view.showdebug = false;
6534
6535                 r_waterstate.enabled = false;
6536                 r_waterstate.numwaterplanes = 0;
6537
6538                 R_RenderScene();
6539
6540                 r_refdef.view.matrix = originalmatrix;
6541
6542                 CHECKGLERROR
6543                 return;
6544         }
6545
6546         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6547         {
6548                 r_refdef.view.matrix = originalmatrix;
6549                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6550         }
6551
6552         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6553
6554         R_RenderView_UpdateViewVectors();
6555
6556         R_Shadow_UpdateWorldLightSelection();
6557
6558         R_Bloom_StartFrame();
6559         R_Water_StartFrame();
6560
6561         CHECKGLERROR
6562         if (r_timereport_active)
6563                 R_TimeReport("viewsetup");
6564
6565         R_ResetViewRendering3D();
6566
6567         if (r_refdef.view.clear || r_refdef.fogenabled)
6568         {
6569                 R_ClearScreen(r_refdef.fogenabled);
6570                 if (r_timereport_active)
6571                         R_TimeReport("viewclear");
6572         }
6573         r_refdef.view.clear = true;
6574
6575         // this produces a bloom texture to be used in R_BlendView() later
6576         if (r_hdr.integer && r_bloomstate.bloomwidth)
6577         {
6578                 R_HDR_RenderBloomTexture();
6579                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6580                 r_textureframe++; // used only by R_GetCurrentTexture
6581         }
6582
6583         r_refdef.view.showdebug = true;
6584
6585         R_View_Update();
6586         if (r_timereport_active)
6587                 R_TimeReport("visibility");
6588
6589         r_waterstate.numwaterplanes = 0;
6590         if (r_waterstate.enabled)
6591                 R_RenderWaterPlanes();
6592
6593         R_RenderScene();
6594         r_waterstate.numwaterplanes = 0;
6595
6596         R_BlendView();
6597         if (r_timereport_active)
6598                 R_TimeReport("blendview");
6599
6600         GL_Scissor(0, 0, vid.width, vid.height);
6601         GL_ScissorTest(false);
6602
6603         r_refdef.view.matrix = originalmatrix;
6604
6605         CHECKGLERROR
6606 }
6607
6608 void R_RenderWaterPlanes(void)
6609 {
6610         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6611         {
6612                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6613                 if (r_timereport_active)
6614                         R_TimeReport("waterworld");
6615         }
6616
6617         // don't let sound skip if going slow
6618         if (r_refdef.scene.extraupdate)
6619                 S_ExtraUpdate ();
6620
6621         R_DrawModelsAddWaterPlanes();
6622         if (r_timereport_active)
6623                 R_TimeReport("watermodels");
6624
6625         if (r_waterstate.numwaterplanes)
6626         {
6627                 R_Water_ProcessPlanes();
6628                 if (r_timereport_active)
6629                         R_TimeReport("waterscenes");
6630         }
6631 }
6632
6633 extern void R_DrawLightningBeams (void);
6634 extern void VM_CL_AddPolygonsToMeshQueue (void);
6635 extern void R_DrawPortals (void);
6636 extern cvar_t cl_locs_show;
6637 static void R_DrawLocs(void);
6638 static void R_DrawEntityBBoxes(void);
6639 static void R_DrawModelDecals(void);
6640 extern void R_DrawModelShadows(void);
6641 extern void R_DrawModelShadowMaps(void);
6642 extern cvar_t cl_decals_newsystem;
6643 extern qboolean r_shadow_usingdeferredprepass;
6644 void R_RenderScene(void)
6645 {
6646         qboolean shadowmapping = false;
6647
6648         if (r_timereport_active)
6649                 R_TimeReport("beginscene");
6650
6651         r_refdef.stats.renders++;
6652
6653         R_UpdateFogColor();
6654
6655         // don't let sound skip if going slow
6656         if (r_refdef.scene.extraupdate)
6657                 S_ExtraUpdate ();
6658
6659         R_MeshQueue_BeginScene();
6660
6661         R_SkyStartFrame();
6662
6663         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);
6664
6665         if (r_timereport_active)
6666                 R_TimeReport("skystartframe");
6667
6668         if (cl.csqc_vidvars.drawworld)
6669         {
6670                 // don't let sound skip if going slow
6671                 if (r_refdef.scene.extraupdate)
6672                         S_ExtraUpdate ();
6673
6674                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6675                 {
6676                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6677                         if (r_timereport_active)
6678                                 R_TimeReport("worldsky");
6679                 }
6680
6681                 if (R_DrawBrushModelsSky() && r_timereport_active)
6682                         R_TimeReport("bmodelsky");
6683
6684                 if (skyrendermasked && skyrenderlater)
6685                 {
6686                         // we have to force off the water clipping plane while rendering sky
6687                         R_SetupView(false);
6688                         R_Sky();
6689                         R_SetupView(true);
6690                         if (r_timereport_active)
6691                                 R_TimeReport("sky");
6692                 }
6693         }
6694
6695         R_AnimCache_CacheVisibleEntities();
6696         if (r_timereport_active)
6697                 R_TimeReport("animation");
6698
6699         R_Shadow_PrepareLights();
6700         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6701                 R_Shadow_PrepareModelShadows();
6702         if (r_timereport_active)
6703                 R_TimeReport("preparelights");
6704
6705         if (R_Shadow_ShadowMappingEnabled())
6706                 shadowmapping = true;
6707
6708         if (r_shadow_usingdeferredprepass)
6709                 R_Shadow_DrawPrepass();
6710
6711         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6712         {
6713                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6714                 if (r_timereport_active)
6715                         R_TimeReport("worlddepth");
6716         }
6717         if (r_depthfirst.integer >= 2)
6718         {
6719                 R_DrawModelsDepth();
6720                 if (r_timereport_active)
6721                         R_TimeReport("modeldepth");
6722         }
6723
6724         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6725         {
6726                 R_DrawModelShadowMaps();
6727                 R_ResetViewRendering3D();
6728                 // don't let sound skip if going slow
6729                 if (r_refdef.scene.extraupdate)
6730                         S_ExtraUpdate ();
6731         }
6732
6733         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6734         {
6735                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6736                 if (r_timereport_active)
6737                         R_TimeReport("world");
6738         }
6739
6740         // don't let sound skip if going slow
6741         if (r_refdef.scene.extraupdate)
6742                 S_ExtraUpdate ();
6743
6744         R_DrawModels();
6745         if (r_timereport_active)
6746                 R_TimeReport("models");
6747
6748         // don't let sound skip if going slow
6749         if (r_refdef.scene.extraupdate)
6750                 S_ExtraUpdate ();
6751
6752         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6753         {
6754                 R_DrawModelShadows();
6755                 R_ResetViewRendering3D();
6756                 // don't let sound skip if going slow
6757                 if (r_refdef.scene.extraupdate)
6758                         S_ExtraUpdate ();
6759         }
6760
6761         if (!r_shadow_usingdeferredprepass)
6762         {
6763                 R_Shadow_DrawLights();
6764                 if (r_timereport_active)
6765                         R_TimeReport("rtlights");
6766         }
6767
6768         // don't let sound skip if going slow
6769         if (r_refdef.scene.extraupdate)
6770                 S_ExtraUpdate ();
6771
6772         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6773         {
6774                 R_DrawModelShadows();
6775                 R_ResetViewRendering3D();
6776                 // don't let sound skip if going slow
6777                 if (r_refdef.scene.extraupdate)
6778                         S_ExtraUpdate ();
6779         }
6780
6781         if (cl.csqc_vidvars.drawworld)
6782         {
6783                 if (cl_decals_newsystem.integer)
6784                 {
6785                         R_DrawModelDecals();
6786                         if (r_timereport_active)
6787                                 R_TimeReport("modeldecals");
6788                 }
6789                 else
6790                 {
6791                         R_DrawDecals();
6792                         if (r_timereport_active)
6793                                 R_TimeReport("decals");
6794                 }
6795
6796                 R_DrawParticles();
6797                 if (r_timereport_active)
6798                         R_TimeReport("particles");
6799
6800                 R_DrawExplosions();
6801                 if (r_timereport_active)
6802                         R_TimeReport("explosions");
6803
6804                 R_DrawLightningBeams();
6805                 if (r_timereport_active)
6806                         R_TimeReport("lightning");
6807         }
6808
6809         VM_CL_AddPolygonsToMeshQueue();
6810
6811         if (r_refdef.view.showdebug)
6812         {
6813                 if (cl_locs_show.integer)
6814                 {
6815                         R_DrawLocs();
6816                         if (r_timereport_active)
6817                                 R_TimeReport("showlocs");
6818                 }
6819
6820                 if (r_drawportals.integer)
6821                 {
6822                         R_DrawPortals();
6823                         if (r_timereport_active)
6824                                 R_TimeReport("portals");
6825                 }
6826
6827                 if (r_showbboxes.value > 0)
6828                 {
6829                         R_DrawEntityBBoxes();
6830                         if (r_timereport_active)
6831                                 R_TimeReport("bboxes");
6832                 }
6833         }
6834
6835         R_MeshQueue_RenderTransparent();
6836         if (r_timereport_active)
6837                 R_TimeReport("drawtrans");
6838
6839         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))
6840         {
6841                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6842                 if (r_timereport_active)
6843                         R_TimeReport("worlddebug");
6844                 R_DrawModelsDebug();
6845                 if (r_timereport_active)
6846                         R_TimeReport("modeldebug");
6847         }
6848
6849         if (cl.csqc_vidvars.drawworld)
6850         {
6851                 R_Shadow_DrawCoronas();
6852                 if (r_timereport_active)
6853                         R_TimeReport("coronas");
6854         }
6855
6856 #if 0
6857         {
6858                 GL_DepthTest(false);
6859                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6860                 GL_Color(1, 1, 1, 1);
6861                 qglBegin(GL_POLYGON);
6862                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6863                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6864                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6865                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6866                 qglEnd();
6867                 qglBegin(GL_POLYGON);
6868                 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]);
6869                 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]);
6870                 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]);
6871                 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]);
6872                 qglEnd();
6873                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6874         }
6875 #endif
6876
6877         // don't let sound skip if going slow
6878         if (r_refdef.scene.extraupdate)
6879                 S_ExtraUpdate ();
6880
6881         R_ResetViewRendering2D();
6882 }
6883
6884 static const unsigned short bboxelements[36] =
6885 {
6886         5, 1, 3, 5, 3, 7,
6887         6, 2, 0, 6, 0, 4,
6888         7, 3, 2, 7, 2, 6,
6889         4, 0, 1, 4, 1, 5,
6890         4, 5, 7, 4, 7, 6,
6891         1, 0, 2, 1, 2, 3,
6892 };
6893
6894 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6895 {
6896         int i;
6897         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6898
6899         RSurf_ActiveWorldEntity();
6900
6901         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6902         GL_DepthMask(false);
6903         GL_DepthRange(0, 1);
6904         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6905 //      R_Mesh_ResetTextureState();
6906
6907         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6908         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6909         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6910         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6911         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6912         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6913         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6914         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6915         R_FillColors(color4f, 8, cr, cg, cb, ca);
6916         if (r_refdef.fogenabled)
6917         {
6918                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6919                 {
6920                         f1 = RSurf_FogVertex(v);
6921                         f2 = 1 - f1;
6922                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6923                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6924                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6925                 }
6926         }
6927         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6928         R_Mesh_ResetTextureState();
6929         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6930         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6931 }
6932
6933 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6934 {
6935         int i;
6936         float color[4];
6937         prvm_edict_t *edict;
6938         prvm_prog_t *prog_save = prog;
6939
6940         // this function draws bounding boxes of server entities
6941         if (!sv.active)
6942                 return;
6943
6944         GL_CullFace(GL_NONE);
6945         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6946
6947         prog = 0;
6948         SV_VM_Begin();
6949         for (i = 0;i < numsurfaces;i++)
6950         {
6951                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6952                 switch ((int)edict->fields.server->solid)
6953                 {
6954                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6955                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6956                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6957                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6958                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6959                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6960                 }
6961                 color[3] *= r_showbboxes.value;
6962                 color[3] = bound(0, color[3], 1);
6963                 GL_DepthTest(!r_showdisabledepthtest.integer);
6964                 GL_CullFace(r_refdef.view.cullface_front);
6965                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6966         }
6967         SV_VM_End();
6968         prog = prog_save;
6969 }
6970
6971 static void R_DrawEntityBBoxes(void)
6972 {
6973         int i;
6974         prvm_edict_t *edict;
6975         vec3_t center;
6976         prvm_prog_t *prog_save = prog;
6977
6978         // this function draws bounding boxes of server entities
6979         if (!sv.active)
6980                 return;
6981
6982         prog = 0;
6983         SV_VM_Begin();
6984         for (i = 0;i < prog->num_edicts;i++)
6985         {
6986                 edict = PRVM_EDICT_NUM(i);
6987                 if (edict->priv.server->free)
6988                         continue;
6989                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6990                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6991                         continue;
6992                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6993                         continue;
6994                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6995                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6996         }
6997         SV_VM_End();
6998         prog = prog_save;
6999 }
7000
7001 static const int nomodelelement3i[24] =
7002 {
7003         5, 2, 0,
7004         5, 1, 2,
7005         5, 0, 3,
7006         5, 3, 1,
7007         0, 2, 4,
7008         2, 1, 4,
7009         3, 0, 4,
7010         1, 3, 4
7011 };
7012
7013 static const unsigned short nomodelelement3s[24] =
7014 {
7015         5, 2, 0,
7016         5, 1, 2,
7017         5, 0, 3,
7018         5, 3, 1,
7019         0, 2, 4,
7020         2, 1, 4,
7021         3, 0, 4,
7022         1, 3, 4
7023 };
7024
7025 static const float nomodelvertex3f[6*3] =
7026 {
7027         -16,   0,   0,
7028          16,   0,   0,
7029           0, -16,   0,
7030           0,  16,   0,
7031           0,   0, -16,
7032           0,   0,  16
7033 };
7034
7035 static const float nomodelcolor4f[6*4] =
7036 {
7037         0.0f, 0.0f, 0.5f, 1.0f,
7038         0.0f, 0.0f, 0.5f, 1.0f,
7039         0.0f, 0.5f, 0.0f, 1.0f,
7040         0.0f, 0.5f, 0.0f, 1.0f,
7041         0.5f, 0.0f, 0.0f, 1.0f,
7042         0.5f, 0.0f, 0.0f, 1.0f
7043 };
7044
7045 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7046 {
7047         int i;
7048         float f1, f2, *c;
7049         float color4f[6*4];
7050
7051         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);
7052
7053         // this is only called once per entity so numsurfaces is always 1, and
7054         // surfacelist is always {0}, so this code does not handle batches
7055
7056         if (rsurface.ent_flags & RENDER_ADDITIVE)
7057         {
7058                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7059                 GL_DepthMask(false);
7060         }
7061         else if (rsurface.colormod[3] < 1)
7062         {
7063                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7064                 GL_DepthMask(false);
7065         }
7066         else
7067         {
7068                 GL_BlendFunc(GL_ONE, GL_ZERO);
7069                 GL_DepthMask(true);
7070         }
7071         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7072         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7073         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7074         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7075         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7076         for (i = 0, c = color4f;i < 6;i++, c += 4)
7077         {
7078                 c[0] *= rsurface.colormod[0];
7079                 c[1] *= rsurface.colormod[1];
7080                 c[2] *= rsurface.colormod[2];
7081                 c[3] *= rsurface.colormod[3];
7082         }
7083         if (r_refdef.fogenabled)
7084         {
7085                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7086                 {
7087                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7088                         f2 = 1 - f1;
7089                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7090                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7091                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7092                 }
7093         }
7094 //      R_Mesh_ResetTextureState();
7095         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7096         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7097         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7098 }
7099
7100 void R_DrawNoModel(entity_render_t *ent)
7101 {
7102         vec3_t org;
7103         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7104         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7105                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7106         else
7107                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7108 }
7109
7110 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7111 {
7112         vec3_t right1, right2, diff, normal;
7113
7114         VectorSubtract (org2, org1, normal);
7115
7116         // calculate 'right' vector for start
7117         VectorSubtract (r_refdef.view.origin, org1, diff);
7118         CrossProduct (normal, diff, right1);
7119         VectorNormalize (right1);
7120
7121         // calculate 'right' vector for end
7122         VectorSubtract (r_refdef.view.origin, org2, diff);
7123         CrossProduct (normal, diff, right2);
7124         VectorNormalize (right2);
7125
7126         vert[ 0] = org1[0] + width * right1[0];
7127         vert[ 1] = org1[1] + width * right1[1];
7128         vert[ 2] = org1[2] + width * right1[2];
7129         vert[ 3] = org1[0] - width * right1[0];
7130         vert[ 4] = org1[1] - width * right1[1];
7131         vert[ 5] = org1[2] - width * right1[2];
7132         vert[ 6] = org2[0] - width * right2[0];
7133         vert[ 7] = org2[1] - width * right2[1];
7134         vert[ 8] = org2[2] - width * right2[2];
7135         vert[ 9] = org2[0] + width * right2[0];
7136         vert[10] = org2[1] + width * right2[1];
7137         vert[11] = org2[2] + width * right2[2];
7138 }
7139
7140 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)
7141 {
7142         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7143         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7144         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7145         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7146         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7147         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7148         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7149         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7150         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7151         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7152         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7153         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7154 }
7155
7156 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7157 {
7158         int i;
7159         float *vertex3f;
7160         float v[3];
7161         VectorSet(v, x, y, z);
7162         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7163                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7164                         break;
7165         if (i == mesh->numvertices)
7166         {
7167                 if (mesh->numvertices < mesh->maxvertices)
7168                 {
7169                         VectorCopy(v, vertex3f);
7170                         mesh->numvertices++;
7171                 }
7172                 return mesh->numvertices;
7173         }
7174         else
7175                 return i;
7176 }
7177
7178 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7179 {
7180         int i;
7181         int *e, element[3];
7182         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7183         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7184         e = mesh->element3i + mesh->numtriangles * 3;
7185         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7186         {
7187                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7188                 if (mesh->numtriangles < mesh->maxtriangles)
7189                 {
7190                         *e++ = element[0];
7191                         *e++ = element[1];
7192                         *e++ = element[2];
7193                         mesh->numtriangles++;
7194                 }
7195                 element[1] = element[2];
7196         }
7197 }
7198
7199 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7200 {
7201         int i;
7202         int *e, element[3];
7203         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7204         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7205         e = mesh->element3i + mesh->numtriangles * 3;
7206         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7207         {
7208                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7209                 if (mesh->numtriangles < mesh->maxtriangles)
7210                 {
7211                         *e++ = element[0];
7212                         *e++ = element[1];
7213                         *e++ = element[2];
7214                         mesh->numtriangles++;
7215                 }
7216                 element[1] = element[2];
7217         }
7218 }
7219
7220 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7221 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7222 {
7223         int planenum, planenum2;
7224         int w;
7225         int tempnumpoints;
7226         mplane_t *plane, *plane2;
7227         double maxdist;
7228         double temppoints[2][256*3];
7229         // figure out how large a bounding box we need to properly compute this brush
7230         maxdist = 0;
7231         for (w = 0;w < numplanes;w++)
7232                 maxdist = max(maxdist, fabs(planes[w].dist));
7233         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7234         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7235         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7236         {
7237                 w = 0;
7238                 tempnumpoints = 4;
7239                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7240                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7241                 {
7242                         if (planenum2 == planenum)
7243                                 continue;
7244                         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);
7245                         w = !w;
7246                 }
7247                 if (tempnumpoints < 3)
7248                         continue;
7249                 // generate elements forming a triangle fan for this polygon
7250                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7251         }
7252 }
7253
7254 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)
7255 {
7256         texturelayer_t *layer;
7257         layer = t->currentlayers + t->currentnumlayers++;
7258         layer->type = type;
7259         layer->depthmask = depthmask;
7260         layer->blendfunc1 = blendfunc1;
7261         layer->blendfunc2 = blendfunc2;
7262         layer->texture = texture;
7263         layer->texmatrix = *matrix;
7264         layer->color[0] = r;
7265         layer->color[1] = g;
7266         layer->color[2] = b;
7267         layer->color[3] = a;
7268 }
7269
7270 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7271 {
7272         if(parms[0] == 0 && parms[1] == 0)
7273                 return false;
7274         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7275                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7276                         return false;
7277         return true;
7278 }
7279
7280 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7281 {
7282         double index, f;
7283         index = parms[2] + r_refdef.scene.time * parms[3];
7284         index -= floor(index);
7285         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7286         {
7287         default:
7288         case Q3WAVEFUNC_NONE:
7289         case Q3WAVEFUNC_NOISE:
7290         case Q3WAVEFUNC_COUNT:
7291                 f = 0;
7292                 break;
7293         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7294         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7295         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7296         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7297         case Q3WAVEFUNC_TRIANGLE:
7298                 index *= 4;
7299                 f = index - floor(index);
7300                 if (index < 1)
7301                         f = f;
7302                 else if (index < 2)
7303                         f = 1 - f;
7304                 else if (index < 3)
7305                         f = -f;
7306                 else
7307                         f = -(1 - f);
7308                 break;
7309         }
7310         f = parms[0] + parms[1] * f;
7311         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7312                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7313         return (float) f;
7314 }
7315
7316 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7317 {
7318         int w, h, idx;
7319         float f;
7320         float tcmat[12];
7321         matrix4x4_t matrix, temp;
7322         switch(tcmod->tcmod)
7323         {
7324                 case Q3TCMOD_COUNT:
7325                 case Q3TCMOD_NONE:
7326                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7327                                 matrix = r_waterscrollmatrix;
7328                         else
7329                                 matrix = identitymatrix;
7330                         break;
7331                 case Q3TCMOD_ENTITYTRANSLATE:
7332                         // this is used in Q3 to allow the gamecode to control texcoord
7333                         // scrolling on the entity, which is not supported in darkplaces yet.
7334                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7335                         break;
7336                 case Q3TCMOD_ROTATE:
7337                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7338                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7339                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7340                         break;
7341                 case Q3TCMOD_SCALE:
7342                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7343                         break;
7344                 case Q3TCMOD_SCROLL:
7345                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7346                         break;
7347                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7348                         w = (int) tcmod->parms[0];
7349                         h = (int) tcmod->parms[1];
7350                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7351                         f = f - floor(f);
7352                         idx = (int) floor(f * w * h);
7353                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7354                         break;
7355                 case Q3TCMOD_STRETCH:
7356                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7357                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7358                         break;
7359                 case Q3TCMOD_TRANSFORM:
7360                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7361                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7362                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7363                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7364                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7365                         break;
7366                 case Q3TCMOD_TURBULENT:
7367                         // this is handled in the RSurf_PrepareVertices function
7368                         matrix = identitymatrix;
7369                         break;
7370         }
7371         temp = *texmatrix;
7372         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7373 }
7374
7375 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7376 {
7377         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7378         char name[MAX_QPATH];
7379         skinframe_t *skinframe;
7380         unsigned char pixels[296*194];
7381         strlcpy(cache->name, skinname, sizeof(cache->name));
7382         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7383         if (developer_loading.integer)
7384                 Con_Printf("loading %s\n", name);
7385         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7386         if (!skinframe || !skinframe->base)
7387         {
7388                 unsigned char *f;
7389                 fs_offset_t filesize;
7390                 skinframe = NULL;
7391                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7392                 if (f)
7393                 {
7394                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7395                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7396                         Mem_Free(f);
7397                 }
7398         }
7399         cache->skinframe = skinframe;
7400 }
7401
7402 texture_t *R_GetCurrentTexture(texture_t *t)
7403 {
7404         int i;
7405         const entity_render_t *ent = rsurface.entity;
7406         dp_model_t *model = ent->model;
7407         q3shaderinfo_layer_tcmod_t *tcmod;
7408
7409         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7410                 return t->currentframe;
7411         t->update_lastrenderframe = r_textureframe;
7412         t->update_lastrenderentity = (void *)ent;
7413
7414         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7415                 t->camera_entity = ent->entitynumber;
7416         else
7417                 t->camera_entity = 0;
7418
7419         // switch to an alternate material if this is a q1bsp animated material
7420         {
7421                 texture_t *texture = t;
7422                 int s = rsurface.ent_skinnum;
7423                 if ((unsigned int)s >= (unsigned int)model->numskins)
7424                         s = 0;
7425                 if (model->skinscenes)
7426                 {
7427                         if (model->skinscenes[s].framecount > 1)
7428                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7429                         else
7430                                 s = model->skinscenes[s].firstframe;
7431                 }
7432                 if (s > 0)
7433                         t = t + s * model->num_surfaces;
7434                 if (t->animated)
7435                 {
7436                         // use an alternate animation if the entity's frame is not 0,
7437                         // and only if the texture has an alternate animation
7438                         if (rsurface.ent_alttextures && t->anim_total[1])
7439                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7440                         else
7441                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7442                 }
7443                 texture->currentframe = t;
7444         }
7445
7446         // update currentskinframe to be a qw skin or animation frame
7447         if (rsurface.ent_qwskin >= 0)
7448         {
7449                 i = rsurface.ent_qwskin;
7450                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7451                 {
7452                         r_qwskincache_size = cl.maxclients;
7453                         if (r_qwskincache)
7454                                 Mem_Free(r_qwskincache);
7455                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7456                 }
7457                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7458                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7459                 t->currentskinframe = r_qwskincache[i].skinframe;
7460                 if (t->currentskinframe == NULL)
7461                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7462         }
7463         else if (t->numskinframes >= 2)
7464                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7465         if (t->backgroundnumskinframes >= 2)
7466                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7467
7468         t->currentmaterialflags = t->basematerialflags;
7469         t->currentalpha = rsurface.colormod[3];
7470         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7471                 t->currentalpha *= r_wateralpha.value;
7472         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7473                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7474         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7475                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7476         if (!(rsurface.ent_flags & RENDER_LIGHT))
7477                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7478         else if (FAKELIGHT_ENABLED)
7479         {
7480                         // no modellight if using fakelight for the map
7481         }
7482         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7483         {
7484                 // pick a model lighting mode
7485                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7486                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7487                 else
7488                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7489         }
7490         if (rsurface.ent_flags & RENDER_ADDITIVE)
7491                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7492         else if (t->currentalpha < 1)
7493                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7494         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7495                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7496         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7497                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7498         if (t->backgroundnumskinframes)
7499                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7500         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7501         {
7502                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7503                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7504         }
7505         else
7506                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7507         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7508                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7509
7510         // there is no tcmod
7511         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7512         {
7513                 t->currenttexmatrix = r_waterscrollmatrix;
7514                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7515         }
7516         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7517         {
7518                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7519                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7520         }
7521
7522         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7523                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7524         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7525                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7526
7527         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7528         if (t->currentskinframe->qpixels)
7529                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7530         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7531         if (!t->basetexture)
7532                 t->basetexture = r_texture_notexture;
7533         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7534         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7535         t->nmaptexture = t->currentskinframe->nmap;
7536         if (!t->nmaptexture)
7537                 t->nmaptexture = r_texture_blanknormalmap;
7538         t->glosstexture = r_texture_black;
7539         t->glowtexture = t->currentskinframe->glow;
7540         t->fogtexture = t->currentskinframe->fog;
7541         t->reflectmasktexture = t->currentskinframe->reflect;
7542         if (t->backgroundnumskinframes)
7543         {
7544                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7545                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7546                 t->backgroundglosstexture = r_texture_black;
7547                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7548                 if (!t->backgroundnmaptexture)
7549                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7550         }
7551         else
7552         {
7553                 t->backgroundbasetexture = r_texture_white;
7554                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7555                 t->backgroundglosstexture = r_texture_black;
7556                 t->backgroundglowtexture = NULL;
7557         }
7558         t->specularpower = r_shadow_glossexponent.value;
7559         // TODO: store reference values for these in the texture?
7560         t->specularscale = 0;
7561         if (r_shadow_gloss.integer > 0)
7562         {
7563                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7564                 {
7565                         if (r_shadow_glossintensity.value > 0)
7566                         {
7567                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7568                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7569                                 t->specularscale = r_shadow_glossintensity.value;
7570                         }
7571                 }
7572                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7573                 {
7574                         t->glosstexture = r_texture_white;
7575                         t->backgroundglosstexture = r_texture_white;
7576                         t->specularscale = r_shadow_gloss2intensity.value;
7577                         t->specularpower = r_shadow_gloss2exponent.value;
7578                 }
7579         }
7580         t->specularscale *= t->specularscalemod;
7581         t->specularpower *= t->specularpowermod;
7582
7583         // lightmaps mode looks bad with dlights using actual texturing, so turn
7584         // off the colormap and glossmap, but leave the normalmap on as it still
7585         // accurately represents the shading involved
7586         if (gl_lightmaps.integer)
7587         {
7588                 t->basetexture = r_texture_grey128;
7589                 t->pantstexture = r_texture_black;
7590                 t->shirttexture = r_texture_black;
7591                 t->nmaptexture = r_texture_blanknormalmap;
7592                 t->glosstexture = r_texture_black;
7593                 t->glowtexture = NULL;
7594                 t->fogtexture = NULL;
7595                 t->reflectmasktexture = NULL;
7596                 t->backgroundbasetexture = NULL;
7597                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7598                 t->backgroundglosstexture = r_texture_black;
7599                 t->backgroundglowtexture = NULL;
7600                 t->specularscale = 0;
7601                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7602         }
7603
7604         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7605         VectorClear(t->dlightcolor);
7606         t->currentnumlayers = 0;
7607         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7608         {
7609                 int blendfunc1, blendfunc2;
7610                 qboolean depthmask;
7611                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7612                 {
7613                         blendfunc1 = GL_SRC_ALPHA;
7614                         blendfunc2 = GL_ONE;
7615                 }
7616                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7617                 {
7618                         blendfunc1 = GL_SRC_ALPHA;
7619                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7620                 }
7621                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7622                 {
7623                         blendfunc1 = t->customblendfunc[0];
7624                         blendfunc2 = t->customblendfunc[1];
7625                 }
7626                 else
7627                 {
7628                         blendfunc1 = GL_ONE;
7629                         blendfunc2 = GL_ZERO;
7630                 }
7631                 // don't colormod evilblend textures
7632                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7633                         VectorSet(t->lightmapcolor, 1, 1, 1);
7634                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7635                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7636                 {
7637                         // fullbright is not affected by r_refdef.lightmapintensity
7638                         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]);
7639                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7640                                 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]);
7641                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7642                                 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]);
7643                 }
7644                 else
7645                 {
7646                         vec3_t ambientcolor;
7647                         float colorscale;
7648                         // set the color tint used for lights affecting this surface
7649                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7650                         colorscale = 2;
7651                         // q3bsp has no lightmap updates, so the lightstylevalue that
7652                         // would normally be baked into the lightmap must be
7653                         // applied to the color
7654                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7655                         if (model->type == mod_brushq3)
7656                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7657                         colorscale *= r_refdef.lightmapintensity;
7658                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7659                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7660                         // basic lit geometry
7661                         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]);
7662                         // add pants/shirt if needed
7663                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7664                                 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]);
7665                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7666                                 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]);
7667                         // now add ambient passes if needed
7668                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7669                         {
7670                                 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]);
7671                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7672                                         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]);
7673                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7674                                         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]);
7675                         }
7676                 }
7677                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7678                         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]);
7679                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7680                 {
7681                         // if this is opaque use alpha blend which will darken the earlier
7682                         // passes cheaply.
7683                         //
7684                         // if this is an alpha blended material, all the earlier passes
7685                         // were darkened by fog already, so we only need to add the fog
7686                         // color ontop through the fog mask texture
7687                         //
7688                         // if this is an additive blended material, all the earlier passes
7689                         // were darkened by fog already, and we should not add fog color
7690                         // (because the background was not darkened, there is no fog color
7691                         // that was lost behind it).
7692                         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]);
7693                 }
7694         }
7695
7696         return t->currentframe;
7697 }
7698
7699 rsurfacestate_t rsurface;
7700
7701 void RSurf_ActiveWorldEntity(void)
7702 {
7703         dp_model_t *model = r_refdef.scene.worldmodel;
7704         //if (rsurface.entity == r_refdef.scene.worldentity)
7705         //      return;
7706         rsurface.entity = r_refdef.scene.worldentity;
7707         rsurface.skeleton = NULL;
7708         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7709         rsurface.ent_skinnum = 0;
7710         rsurface.ent_qwskin = -1;
7711         rsurface.ent_shadertime = 0;
7712         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7713         rsurface.matrix = identitymatrix;
7714         rsurface.inversematrix = identitymatrix;
7715         rsurface.matrixscale = 1;
7716         rsurface.inversematrixscale = 1;
7717         R_EntityMatrix(&identitymatrix);
7718         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7719         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7720         rsurface.fograngerecip = r_refdef.fograngerecip;
7721         rsurface.fogheightfade = r_refdef.fogheightfade;
7722         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7723         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7724         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7725         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7726         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7727         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7728         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7729         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7730         rsurface.colormod[3] = 1;
7731         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);
7732         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7733         rsurface.frameblend[0].lerp = 1;
7734         rsurface.ent_alttextures = false;
7735         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7736         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7737         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7738         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7739         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7740         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7741         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7742         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7743         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7744         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7745         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7746         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7747         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7748         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7749         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7750         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7751         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7752         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7753         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7754         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7755         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7756         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7757         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7758         rsurface.modelelement3i = model->surfmesh.data_element3i;
7759         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7760         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7761         rsurface.modelelement3s = model->surfmesh.data_element3s;
7762         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7763         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7764         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7765         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7766         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7767         rsurface.modelsurfaces = model->data_surfaces;
7768         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7769         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7770         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7771         rsurface.modelgeneratedvertex = false;
7772         rsurface.batchgeneratedvertex = false;
7773         rsurface.batchfirstvertex = 0;
7774         rsurface.batchnumvertices = 0;
7775         rsurface.batchfirsttriangle = 0;
7776         rsurface.batchnumtriangles = 0;
7777         rsurface.batchvertex3f  = NULL;
7778         rsurface.batchvertex3f_vertexbuffer = NULL;
7779         rsurface.batchvertex3f_bufferoffset = 0;
7780         rsurface.batchsvector3f = NULL;
7781         rsurface.batchsvector3f_vertexbuffer = NULL;
7782         rsurface.batchsvector3f_bufferoffset = 0;
7783         rsurface.batchtvector3f = NULL;
7784         rsurface.batchtvector3f_vertexbuffer = NULL;
7785         rsurface.batchtvector3f_bufferoffset = 0;
7786         rsurface.batchnormal3f  = NULL;
7787         rsurface.batchnormal3f_vertexbuffer = NULL;
7788         rsurface.batchnormal3f_bufferoffset = 0;
7789         rsurface.batchlightmapcolor4f = NULL;
7790         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7791         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7792         rsurface.batchtexcoordtexture2f = NULL;
7793         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7794         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7795         rsurface.batchtexcoordlightmap2f = NULL;
7796         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7797         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7798         rsurface.batchvertexmesh = NULL;
7799         rsurface.batchvertexmeshbuffer = NULL;
7800         rsurface.batchvertex3fbuffer = NULL;
7801         rsurface.batchelement3i = NULL;
7802         rsurface.batchelement3i_indexbuffer = NULL;
7803         rsurface.batchelement3i_bufferoffset = 0;
7804         rsurface.batchelement3s = NULL;
7805         rsurface.batchelement3s_indexbuffer = NULL;
7806         rsurface.batchelement3s_bufferoffset = 0;
7807         rsurface.passcolor4f = NULL;
7808         rsurface.passcolor4f_vertexbuffer = NULL;
7809         rsurface.passcolor4f_bufferoffset = 0;
7810 }
7811
7812 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7813 {
7814         dp_model_t *model = ent->model;
7815         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7816         //      return;
7817         rsurface.entity = (entity_render_t *)ent;
7818         rsurface.skeleton = ent->skeleton;
7819         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7820         rsurface.ent_skinnum = ent->skinnum;
7821         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;
7822         rsurface.ent_shadertime = ent->shadertime;
7823         rsurface.ent_flags = ent->flags;
7824         rsurface.matrix = ent->matrix;
7825         rsurface.inversematrix = ent->inversematrix;
7826         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7827         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7828         R_EntityMatrix(&rsurface.matrix);
7829         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7830         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7831         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7832         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7833         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7834         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7835         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7836         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7837         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7838         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7839         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7840         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7841         rsurface.colormod[3] = ent->alpha;
7842         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7843         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7844         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7845         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7846         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7847         if (ent->model->brush.submodel && !prepass)
7848         {
7849                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7850                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7851         }
7852         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7853         {
7854                 if (ent->animcache_vertex3f)
7855                 {
7856                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7857                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7858                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7859                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7860                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7861                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7862                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7863                 }
7864                 else if (wanttangents)
7865                 {
7866                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7867                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7868                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7869                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7870                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7871                         rsurface.modelvertexmesh = NULL;
7872                         rsurface.modelvertexmeshbuffer = NULL;
7873                         rsurface.modelvertex3fbuffer = NULL;
7874                 }
7875                 else if (wantnormals)
7876                 {
7877                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878                         rsurface.modelsvector3f = NULL;
7879                         rsurface.modeltvector3f = NULL;
7880                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7881                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7882                         rsurface.modelvertexmesh = NULL;
7883                         rsurface.modelvertexmeshbuffer = NULL;
7884                         rsurface.modelvertex3fbuffer = NULL;
7885                 }
7886                 else
7887                 {
7888                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7889                         rsurface.modelsvector3f = NULL;
7890                         rsurface.modeltvector3f = NULL;
7891                         rsurface.modelnormal3f = NULL;
7892                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7893                         rsurface.modelvertexmesh = NULL;
7894                         rsurface.modelvertexmeshbuffer = NULL;
7895                         rsurface.modelvertex3fbuffer = NULL;
7896                 }
7897                 rsurface.modelvertex3f_vertexbuffer = 0;
7898                 rsurface.modelvertex3f_bufferoffset = 0;
7899                 rsurface.modelsvector3f_vertexbuffer = 0;
7900                 rsurface.modelsvector3f_bufferoffset = 0;
7901                 rsurface.modeltvector3f_vertexbuffer = 0;
7902                 rsurface.modeltvector3f_bufferoffset = 0;
7903                 rsurface.modelnormal3f_vertexbuffer = 0;
7904                 rsurface.modelnormal3f_bufferoffset = 0;
7905                 rsurface.modelgeneratedvertex = true;
7906         }
7907         else
7908         {
7909                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7910                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7911                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7912                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7913                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7914                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7915                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7916                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7917                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7918                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7919                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7920                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7921                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7922                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7923                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7924                 rsurface.modelgeneratedvertex = false;
7925         }
7926         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7927         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7929         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7930         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7931         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7932         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7933         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7934         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7935         rsurface.modelelement3i = model->surfmesh.data_element3i;
7936         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7937         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7938         rsurface.modelelement3s = model->surfmesh.data_element3s;
7939         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7940         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7941         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7942         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7943         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7944         rsurface.modelsurfaces = model->data_surfaces;
7945         rsurface.batchgeneratedvertex = false;
7946         rsurface.batchfirstvertex = 0;
7947         rsurface.batchnumvertices = 0;
7948         rsurface.batchfirsttriangle = 0;
7949         rsurface.batchnumtriangles = 0;
7950         rsurface.batchvertex3f  = NULL;
7951         rsurface.batchvertex3f_vertexbuffer = NULL;
7952         rsurface.batchvertex3f_bufferoffset = 0;
7953         rsurface.batchsvector3f = NULL;
7954         rsurface.batchsvector3f_vertexbuffer = NULL;
7955         rsurface.batchsvector3f_bufferoffset = 0;
7956         rsurface.batchtvector3f = NULL;
7957         rsurface.batchtvector3f_vertexbuffer = NULL;
7958         rsurface.batchtvector3f_bufferoffset = 0;
7959         rsurface.batchnormal3f  = NULL;
7960         rsurface.batchnormal3f_vertexbuffer = NULL;
7961         rsurface.batchnormal3f_bufferoffset = 0;
7962         rsurface.batchlightmapcolor4f = NULL;
7963         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7964         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7965         rsurface.batchtexcoordtexture2f = NULL;
7966         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7967         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7968         rsurface.batchtexcoordlightmap2f = NULL;
7969         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7970         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7971         rsurface.batchvertexmesh = NULL;
7972         rsurface.batchvertexmeshbuffer = NULL;
7973         rsurface.batchvertex3fbuffer = NULL;
7974         rsurface.batchelement3i = NULL;
7975         rsurface.batchelement3i_indexbuffer = NULL;
7976         rsurface.batchelement3i_bufferoffset = 0;
7977         rsurface.batchelement3s = NULL;
7978         rsurface.batchelement3s_indexbuffer = NULL;
7979         rsurface.batchelement3s_bufferoffset = 0;
7980         rsurface.passcolor4f = NULL;
7981         rsurface.passcolor4f_vertexbuffer = NULL;
7982         rsurface.passcolor4f_bufferoffset = 0;
7983 }
7984
7985 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)
7986 {
7987         rsurface.entity = r_refdef.scene.worldentity;
7988         rsurface.skeleton = NULL;
7989         rsurface.ent_skinnum = 0;
7990         rsurface.ent_qwskin = -1;
7991         rsurface.ent_shadertime = shadertime;
7992         rsurface.ent_flags = entflags;
7993         rsurface.modelnumvertices = numvertices;
7994         rsurface.modelnumtriangles = numtriangles;
7995         rsurface.matrix = *matrix;
7996         rsurface.inversematrix = *inversematrix;
7997         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7998         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7999         R_EntityMatrix(&rsurface.matrix);
8000         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8001         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8002         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8003         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8004         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8005         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8006         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8007         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8008         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8009         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8010         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8011         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8012         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);
8013         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8014         rsurface.frameblend[0].lerp = 1;
8015         rsurface.ent_alttextures = false;
8016         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8017         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8018         if (wanttangents)
8019         {
8020                 rsurface.modelvertex3f = (float *)vertex3f;
8021                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8022                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8023                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8024         }
8025         else if (wantnormals)
8026         {
8027                 rsurface.modelvertex3f = (float *)vertex3f;
8028                 rsurface.modelsvector3f = NULL;
8029                 rsurface.modeltvector3f = NULL;
8030                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8031         }
8032         else
8033         {
8034                 rsurface.modelvertex3f = (float *)vertex3f;
8035                 rsurface.modelsvector3f = NULL;
8036                 rsurface.modeltvector3f = NULL;
8037                 rsurface.modelnormal3f = NULL;
8038         }
8039         rsurface.modelvertexmesh = NULL;
8040         rsurface.modelvertexmeshbuffer = NULL;
8041         rsurface.modelvertex3fbuffer = NULL;
8042         rsurface.modelvertex3f_vertexbuffer = 0;
8043         rsurface.modelvertex3f_bufferoffset = 0;
8044         rsurface.modelsvector3f_vertexbuffer = 0;
8045         rsurface.modelsvector3f_bufferoffset = 0;
8046         rsurface.modeltvector3f_vertexbuffer = 0;
8047         rsurface.modeltvector3f_bufferoffset = 0;
8048         rsurface.modelnormal3f_vertexbuffer = 0;
8049         rsurface.modelnormal3f_bufferoffset = 0;
8050         rsurface.modelgeneratedvertex = true;
8051         rsurface.modellightmapcolor4f  = (float *)color4f;
8052         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8053         rsurface.modellightmapcolor4f_bufferoffset = 0;
8054         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8055         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8056         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8057         rsurface.modeltexcoordlightmap2f  = NULL;
8058         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8059         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8060         rsurface.modelelement3i = (int *)element3i;
8061         rsurface.modelelement3i_indexbuffer = NULL;
8062         rsurface.modelelement3i_bufferoffset = 0;
8063         rsurface.modelelement3s = (unsigned short *)element3s;
8064         rsurface.modelelement3s_indexbuffer = NULL;
8065         rsurface.modelelement3s_bufferoffset = 0;
8066         rsurface.modellightmapoffsets = NULL;
8067         rsurface.modelsurfaces = NULL;
8068         rsurface.batchgeneratedvertex = false;
8069         rsurface.batchfirstvertex = 0;
8070         rsurface.batchnumvertices = 0;
8071         rsurface.batchfirsttriangle = 0;
8072         rsurface.batchnumtriangles = 0;
8073         rsurface.batchvertex3f  = NULL;
8074         rsurface.batchvertex3f_vertexbuffer = NULL;
8075         rsurface.batchvertex3f_bufferoffset = 0;
8076         rsurface.batchsvector3f = NULL;
8077         rsurface.batchsvector3f_vertexbuffer = NULL;
8078         rsurface.batchsvector3f_bufferoffset = 0;
8079         rsurface.batchtvector3f = NULL;
8080         rsurface.batchtvector3f_vertexbuffer = NULL;
8081         rsurface.batchtvector3f_bufferoffset = 0;
8082         rsurface.batchnormal3f  = NULL;
8083         rsurface.batchnormal3f_vertexbuffer = NULL;
8084         rsurface.batchnormal3f_bufferoffset = 0;
8085         rsurface.batchlightmapcolor4f = NULL;
8086         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8087         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8088         rsurface.batchtexcoordtexture2f = NULL;
8089         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8090         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8091         rsurface.batchtexcoordlightmap2f = NULL;
8092         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8093         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8094         rsurface.batchvertexmesh = NULL;
8095         rsurface.batchvertexmeshbuffer = NULL;
8096         rsurface.batchvertex3fbuffer = NULL;
8097         rsurface.batchelement3i = NULL;
8098         rsurface.batchelement3i_indexbuffer = NULL;
8099         rsurface.batchelement3i_bufferoffset = 0;
8100         rsurface.batchelement3s = NULL;
8101         rsurface.batchelement3s_indexbuffer = NULL;
8102         rsurface.batchelement3s_bufferoffset = 0;
8103         rsurface.passcolor4f = NULL;
8104         rsurface.passcolor4f_vertexbuffer = NULL;
8105         rsurface.passcolor4f_bufferoffset = 0;
8106
8107         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8108         {
8109                 if ((wantnormals || wanttangents) && !normal3f)
8110                 {
8111                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8112                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8113                 }
8114                 if (wanttangents && !svector3f)
8115                 {
8116                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8117                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8118                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8119                 }
8120         }
8121 }
8122
8123 float RSurf_FogPoint(const float *v)
8124 {
8125         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8126         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8127         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8128         float FogHeightFade = r_refdef.fogheightfade;
8129         float fogfrac;
8130         unsigned int fogmasktableindex;
8131         if (r_refdef.fogplaneviewabove)
8132                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8133         else
8134                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8135         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8136         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8137 }
8138
8139 float RSurf_FogVertex(const float *v)
8140 {
8141         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8142         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8143         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8144         float FogHeightFade = rsurface.fogheightfade;
8145         float fogfrac;
8146         unsigned int fogmasktableindex;
8147         if (r_refdef.fogplaneviewabove)
8148                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8149         else
8150                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8151         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8152         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8153 }
8154
8155 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8156 {
8157         int i;
8158         for (i = 0;i < numelements;i++)
8159                 outelement3i[i] = inelement3i[i] + adjust;
8160 }
8161
8162 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8163 extern cvar_t gl_vbo;
8164 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8165 {
8166         int deformindex;
8167         int firsttriangle;
8168         int numtriangles;
8169         int firstvertex;
8170         int endvertex;
8171         int numvertices;
8172         int surfacefirsttriangle;
8173         int surfacenumtriangles;
8174         int surfacefirstvertex;
8175         int surfaceendvertex;
8176         int surfacenumvertices;
8177         int batchnumvertices;
8178         int batchnumtriangles;
8179         int needsupdate;
8180         int i, j;
8181         qboolean gaps;
8182         qboolean dynamicvertex;
8183         float amplitude;
8184         float animpos;
8185         float scale;
8186         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8187         float waveparms[4];
8188         q3shaderinfo_deform_t *deform;
8189         const msurface_t *surface, *firstsurface;
8190         r_vertexmesh_t *vertexmesh;
8191         if (!texturenumsurfaces)
8192                 return;
8193         // find vertex range of this surface batch
8194         gaps = false;
8195         firstsurface = texturesurfacelist[0];
8196         firsttriangle = firstsurface->num_firsttriangle;
8197         batchnumvertices = 0;
8198         batchnumtriangles = 0;
8199         firstvertex = endvertex = firstsurface->num_firstvertex;
8200         for (i = 0;i < texturenumsurfaces;i++)
8201         {
8202                 surface = texturesurfacelist[i];
8203                 if (surface != firstsurface + i)
8204                         gaps = true;
8205                 surfacefirstvertex = surface->num_firstvertex;
8206                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8207                 surfacenumvertices = surface->num_vertices;
8208                 surfacenumtriangles = surface->num_triangles;
8209                 if (firstvertex > surfacefirstvertex)
8210                         firstvertex = surfacefirstvertex;
8211                 if (endvertex < surfaceendvertex)
8212                         endvertex = surfaceendvertex;
8213                 batchnumvertices += surfacenumvertices;
8214                 batchnumtriangles += surfacenumtriangles;
8215         }
8216
8217         // we now know the vertex range used, and if there are any gaps in it
8218         rsurface.batchfirstvertex = firstvertex;
8219         rsurface.batchnumvertices = endvertex - firstvertex;
8220         rsurface.batchfirsttriangle = firsttriangle;
8221         rsurface.batchnumtriangles = batchnumtriangles;
8222
8223         // this variable holds flags for which properties have been updated that
8224         // may require regenerating vertexmesh array...
8225         needsupdate = 0;
8226
8227         // check if any dynamic vertex processing must occur
8228         dynamicvertex = false;
8229
8230         // if there is a chance of animated vertex colors, it's a dynamic batch
8231         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8232         {
8233                 dynamicvertex = true;
8234                 batchneed |= BATCHNEED_NOGAPS;
8235                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8236         }
8237
8238         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8239         {
8240                 switch (deform->deform)
8241                 {
8242                 default:
8243                 case Q3DEFORM_PROJECTIONSHADOW:
8244                 case Q3DEFORM_TEXT0:
8245                 case Q3DEFORM_TEXT1:
8246                 case Q3DEFORM_TEXT2:
8247                 case Q3DEFORM_TEXT3:
8248                 case Q3DEFORM_TEXT4:
8249                 case Q3DEFORM_TEXT5:
8250                 case Q3DEFORM_TEXT6:
8251                 case Q3DEFORM_TEXT7:
8252                 case Q3DEFORM_NONE:
8253                         break;
8254                 case Q3DEFORM_AUTOSPRITE:
8255                         dynamicvertex = true;
8256                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8257                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8258                         break;
8259                 case Q3DEFORM_AUTOSPRITE2:
8260                         dynamicvertex = true;
8261                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8262                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8263                         break;
8264                 case Q3DEFORM_NORMAL:
8265                         dynamicvertex = true;
8266                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8267                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8268                         break;
8269                 case Q3DEFORM_WAVE:
8270                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8271                                 break; // if wavefunc is a nop, ignore this transform
8272                         dynamicvertex = true;
8273                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8274                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8275                         break;
8276                 case Q3DEFORM_BULGE:
8277                         dynamicvertex = true;
8278                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8279                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8280                         break;
8281                 case Q3DEFORM_MOVE:
8282                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8283                                 break; // if wavefunc is a nop, ignore this transform
8284                         dynamicvertex = true;
8285                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8286                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8287                         break;
8288                 }
8289         }
8290         switch(rsurface.texture->tcgen.tcgen)
8291         {
8292         default:
8293         case Q3TCGEN_TEXTURE:
8294                 break;
8295         case Q3TCGEN_LIGHTMAP:
8296                 dynamicvertex = true;
8297                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8298                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8299                 break;
8300         case Q3TCGEN_VECTOR:
8301                 dynamicvertex = true;
8302                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8303                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8304                 break;
8305         case Q3TCGEN_ENVIRONMENT:
8306                 dynamicvertex = true;
8307                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8308                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8309                 break;
8310         }
8311         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8312         {
8313                 dynamicvertex = true;
8314                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8315                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8316         }
8317
8318         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8319         {
8320                 dynamicvertex = true;
8321                 batchneed |= BATCHNEED_NOGAPS;
8322                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8323         }
8324
8325         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8326         {
8327                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8328                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8329                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8330                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8331                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8332                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8333                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8334         }
8335
8336         // when the model data has no vertex buffer (dynamic mesh), we need to
8337         // eliminate gaps
8338         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8339                 batchneed |= BATCHNEED_NOGAPS;
8340
8341         // if needsupdate, we have to do a dynamic vertex batch for sure
8342         if (needsupdate & batchneed)
8343                 dynamicvertex = true;
8344
8345         // see if we need to build vertexmesh from arrays
8346         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8347                 dynamicvertex = true;
8348
8349         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8350         // also some drivers strongly dislike firstvertex
8351         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8352                 dynamicvertex = true;
8353
8354         rsurface.batchvertex3f = rsurface.modelvertex3f;
8355         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8356         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8357         rsurface.batchsvector3f = rsurface.modelsvector3f;
8358         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8359         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8360         rsurface.batchtvector3f = rsurface.modeltvector3f;
8361         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8362         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8363         rsurface.batchnormal3f = rsurface.modelnormal3f;
8364         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8365         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8366         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8367         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8368         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8369         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8370         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8371         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8372         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8373         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8374         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8375         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8376         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8377         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8378         rsurface.batchelement3i = rsurface.modelelement3i;
8379         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8380         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8381         rsurface.batchelement3s = rsurface.modelelement3s;
8382         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8383         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8384
8385         // if any dynamic vertex processing has to occur in software, we copy the
8386         // entire surface list together before processing to rebase the vertices
8387         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8388         //
8389         // if any gaps exist and we do not have a static vertex buffer, we have to
8390         // copy the surface list together to avoid wasting upload bandwidth on the
8391         // vertices in the gaps.
8392         //
8393         // if gaps exist and we have a static vertex buffer, we still have to
8394         // combine the index buffer ranges into one dynamic index buffer.
8395         //
8396         // in all cases we end up with data that can be drawn in one call.
8397
8398         if (!dynamicvertex)
8399         {
8400                 // static vertex data, just set pointers...
8401                 rsurface.batchgeneratedvertex = false;
8402                 // if there are gaps, we want to build a combined index buffer,
8403                 // otherwise use the original static buffer with an appropriate offset
8404                 if (gaps)
8405                 {
8406                         // build a new triangle elements array for this batch
8407                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8408                         rsurface.batchfirsttriangle = 0;
8409                         numtriangles = 0;
8410                         for (i = 0;i < texturenumsurfaces;i++)
8411                         {
8412                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8413                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8414                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8415                                 numtriangles += surfacenumtriangles;
8416                         }
8417                         rsurface.batchelement3i_indexbuffer = NULL;
8418                         rsurface.batchelement3i_bufferoffset = 0;
8419                         rsurface.batchelement3s = NULL;
8420                         rsurface.batchelement3s_indexbuffer = NULL;
8421                         rsurface.batchelement3s_bufferoffset = 0;
8422                         if (endvertex <= 65536)
8423                         {
8424                                 // make a 16bit (unsigned short) index array if possible
8425                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8426                                 for (i = 0;i < numtriangles*3;i++)
8427                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8428                         }
8429                 }
8430                 return;
8431         }
8432
8433         // something needs software processing, do it for real...
8434         // we only directly handle separate array data in this case and then
8435         // generate interleaved data if needed...
8436         rsurface.batchgeneratedvertex = true;
8437
8438         // now copy the vertex data into a combined array and make an index array
8439         // (this is what Quake3 does all the time)
8440         //if (gaps || rsurface.batchfirstvertex)
8441         {
8442                 rsurface.batchvertex3fbuffer = NULL;
8443                 rsurface.batchvertexmesh = NULL;
8444                 rsurface.batchvertexmeshbuffer = NULL;
8445                 rsurface.batchvertex3f = NULL;
8446                 rsurface.batchvertex3f_vertexbuffer = NULL;
8447                 rsurface.batchvertex3f_bufferoffset = 0;
8448                 rsurface.batchsvector3f = NULL;
8449                 rsurface.batchsvector3f_vertexbuffer = NULL;
8450                 rsurface.batchsvector3f_bufferoffset = 0;
8451                 rsurface.batchtvector3f = NULL;
8452                 rsurface.batchtvector3f_vertexbuffer = NULL;
8453                 rsurface.batchtvector3f_bufferoffset = 0;
8454                 rsurface.batchnormal3f = NULL;
8455                 rsurface.batchnormal3f_vertexbuffer = NULL;
8456                 rsurface.batchnormal3f_bufferoffset = 0;
8457                 rsurface.batchlightmapcolor4f = NULL;
8458                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8459                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8460                 rsurface.batchtexcoordtexture2f = NULL;
8461                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8462                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8463                 rsurface.batchtexcoordlightmap2f = NULL;
8464                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8465                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8466                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8467                 rsurface.batchelement3i_indexbuffer = NULL;
8468                 rsurface.batchelement3i_bufferoffset = 0;
8469                 rsurface.batchelement3s = NULL;
8470                 rsurface.batchelement3s_indexbuffer = NULL;
8471                 rsurface.batchelement3s_bufferoffset = 0;
8472                 // we'll only be setting up certain arrays as needed
8473                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8474                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8475                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8476                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8477                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8478                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8479                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8480                 {
8481                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8482                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8483                 }
8484                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8485                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8486                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8487                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8488                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8489                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8490                 numvertices = 0;
8491                 numtriangles = 0;
8492                 for (i = 0;i < texturenumsurfaces;i++)
8493                 {
8494                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8495                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8496                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8497                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8498                         // copy only the data requested
8499                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8500                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8501                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8502                         {
8503                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8504                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8505                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8506                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8507                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8508                                 {
8509                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8510                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8511                                 }
8512                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8513                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8514                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8515                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8516                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8517                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8518                         }
8519                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8520                         numvertices += surfacenumvertices;
8521                         numtriangles += surfacenumtriangles;
8522                 }
8523
8524                 // generate a 16bit index array as well if possible
8525                 // (in general, dynamic batches fit)
8526                 if (numvertices <= 65536)
8527                 {
8528                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8529                         for (i = 0;i < numtriangles*3;i++)
8530                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8531                 }
8532
8533                 // since we've copied everything, the batch now starts at 0
8534                 rsurface.batchfirstvertex = 0;
8535                 rsurface.batchnumvertices = batchnumvertices;
8536                 rsurface.batchfirsttriangle = 0;
8537                 rsurface.batchnumtriangles = batchnumtriangles;
8538         }
8539
8540         // q1bsp surfaces rendered in vertex color mode have to have colors
8541         // calculated based on lightstyles
8542         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8543         {
8544                 // generate color arrays for the surfaces in this list
8545                 int c[4];
8546                 int scale;
8547                 int size3;
8548                 const int *offsets;
8549                 const unsigned char *lm;
8550                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8551                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8552                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8553                 numvertices = 0;
8554                 for (i = 0;i < texturenumsurfaces;i++)
8555                 {
8556                         surface = texturesurfacelist[i];
8557                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8558                         surfacenumvertices = surface->num_vertices;
8559                         if (surface->lightmapinfo->samples)
8560                         {
8561                                 for (j = 0;j < surfacenumvertices;j++)
8562                                 {
8563                                         lm = surface->lightmapinfo->samples + offsets[j];
8564                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8565                                         VectorScale(lm, scale, c);
8566                                         if (surface->lightmapinfo->styles[1] != 255)
8567                                         {
8568                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8569                                                 lm += size3;
8570                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8571                                                 VectorMA(c, scale, lm, c);
8572                                                 if (surface->lightmapinfo->styles[2] != 255)
8573                                                 {
8574                                                         lm += size3;
8575                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8576                                                         VectorMA(c, scale, lm, c);
8577                                                         if (surface->lightmapinfo->styles[3] != 255)
8578                                                         {
8579                                                                 lm += size3;
8580                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8581                                                                 VectorMA(c, scale, lm, c);
8582                                                         }
8583                                                 }
8584                                         }
8585                                         c[0] >>= 7;
8586                                         c[1] >>= 7;
8587                                         c[2] >>= 7;
8588                                         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);
8589                                         numvertices++;
8590                                 }
8591                         }
8592                         else
8593                         {
8594                                 for (j = 0;j < surfacenumvertices;j++)
8595                                 {
8596                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8597                                         numvertices++;
8598                                 }
8599                         }
8600                 }
8601         }
8602
8603         // if vertices are deformed (sprite flares and things in maps, possibly
8604         // water waves, bulges and other deformations), modify the copied vertices
8605         // in place
8606         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8607         {
8608                 switch (deform->deform)
8609                 {
8610                 default:
8611                 case Q3DEFORM_PROJECTIONSHADOW:
8612                 case Q3DEFORM_TEXT0:
8613                 case Q3DEFORM_TEXT1:
8614                 case Q3DEFORM_TEXT2:
8615                 case Q3DEFORM_TEXT3:
8616                 case Q3DEFORM_TEXT4:
8617                 case Q3DEFORM_TEXT5:
8618                 case Q3DEFORM_TEXT6:
8619                 case Q3DEFORM_TEXT7:
8620                 case Q3DEFORM_NONE:
8621                         break;
8622                 case Q3DEFORM_AUTOSPRITE:
8623                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8624                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8625                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8626                         VectorNormalize(newforward);
8627                         VectorNormalize(newright);
8628                         VectorNormalize(newup);
8629 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8630 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8631 //                      rsurface.batchvertex3f_bufferoffset = 0;
8632 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8633 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8634 //                      rsurface.batchsvector3f_bufferoffset = 0;
8635 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8636 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8637 //                      rsurface.batchtvector3f_bufferoffset = 0;
8638 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8639 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8640 //                      rsurface.batchnormal3f_bufferoffset = 0;
8641                         // a single autosprite surface can contain multiple sprites...
8642                         for (j = 0;j < batchnumvertices - 3;j += 4)
8643                         {
8644                                 VectorClear(center);
8645                                 for (i = 0;i < 4;i++)
8646                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8647                                 VectorScale(center, 0.25f, center);
8648                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8649                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8650                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8651                                 for (i = 0;i < 4;i++)
8652                                 {
8653                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8654                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8655                                 }
8656                         }
8657                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8658                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8659                         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);
8660                         break;
8661                 case Q3DEFORM_AUTOSPRITE2:
8662                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8663                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8664                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8665                         VectorNormalize(newforward);
8666                         VectorNormalize(newright);
8667                         VectorNormalize(newup);
8668 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8669 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8670 //                      rsurface.batchvertex3f_bufferoffset = 0;
8671                         {
8672                                 const float *v1, *v2;
8673                                 vec3_t start, end;
8674                                 float f, l;
8675                                 struct
8676                                 {
8677                                         float length2;
8678                                         const float *v1;
8679                                         const float *v2;
8680                                 }
8681                                 shortest[2];
8682                                 memset(shortest, 0, sizeof(shortest));
8683                                 // a single autosprite surface can contain multiple sprites...
8684                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8685                                 {
8686                                         VectorClear(center);
8687                                         for (i = 0;i < 4;i++)
8688                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8689                                         VectorScale(center, 0.25f, center);
8690                                         // find the two shortest edges, then use them to define the
8691                                         // axis vectors for rotating around the central axis
8692                                         for (i = 0;i < 6;i++)
8693                                         {
8694                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8695                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8696                                                 l = VectorDistance2(v1, v2);
8697                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8698                                                 if (v1[2] != v2[2])
8699                                                         l += (1.0f / 1024.0f);
8700                                                 if (shortest[0].length2 > l || i == 0)
8701                                                 {
8702                                                         shortest[1] = shortest[0];
8703                                                         shortest[0].length2 = l;
8704                                                         shortest[0].v1 = v1;
8705                                                         shortest[0].v2 = v2;
8706                                                 }
8707                                                 else if (shortest[1].length2 > l || i == 1)
8708                                                 {
8709                                                         shortest[1].length2 = l;
8710                                                         shortest[1].v1 = v1;
8711                                                         shortest[1].v2 = v2;
8712                                                 }
8713                                         }
8714                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8715                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8716                                         // this calculates the right vector from the shortest edge
8717                                         // and the up vector from the edge midpoints
8718                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8719                                         VectorNormalize(right);
8720                                         VectorSubtract(end, start, up);
8721                                         VectorNormalize(up);
8722                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8723                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8724                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8725                                         VectorNegate(forward, forward);
8726                                         VectorReflect(forward, 0, up, forward);
8727                                         VectorNormalize(forward);
8728                                         CrossProduct(up, forward, newright);
8729                                         VectorNormalize(newright);
8730                                         // rotate the quad around the up axis vector, this is made
8731                                         // especially easy by the fact we know the quad is flat,
8732                                         // so we only have to subtract the center position and
8733                                         // measure distance along the right vector, and then
8734                                         // multiply that by the newright vector and add back the
8735                                         // center position
8736                                         // we also need to subtract the old position to undo the
8737                                         // displacement from the center, which we do with a
8738                                         // DotProduct, the subtraction/addition of center is also
8739                                         // optimized into DotProducts here
8740                                         l = DotProduct(right, center);
8741                                         for (i = 0;i < 4;i++)
8742                                         {
8743                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8744                                                 f = DotProduct(right, v1) - l;
8745                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8746                                         }
8747                                 }
8748                         }
8749                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8750                         {
8751 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8752 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8753 //                              rsurface.batchnormal3f_bufferoffset = 0;
8754                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8755                         }
8756                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8757                         {
8758 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8759 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8760 //                              rsurface.batchsvector3f_bufferoffset = 0;
8761 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8762 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8763 //                              rsurface.batchtvector3f_bufferoffset = 0;
8764                                 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);
8765                         }
8766                         break;
8767                 case Q3DEFORM_NORMAL:
8768                         // deform the normals to make reflections wavey
8769                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8770                         rsurface.batchnormal3f_vertexbuffer = NULL;
8771                         rsurface.batchnormal3f_bufferoffset = 0;
8772                         for (j = 0;j < batchnumvertices;j++)
8773                         {
8774                                 float vertex[3];
8775                                 float *normal = rsurface.batchnormal3f + 3*j;
8776                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8777                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8778                                 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]);
8779                                 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]);
8780                                 VectorNormalize(normal);
8781                         }
8782                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8783                         {
8784 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8785 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8786 //                              rsurface.batchsvector3f_bufferoffset = 0;
8787 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8788 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8789 //                              rsurface.batchtvector3f_bufferoffset = 0;
8790                                 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);
8791                         }
8792                         break;
8793                 case Q3DEFORM_WAVE:
8794                         // deform vertex array to make wavey water and flags and such
8795                         waveparms[0] = deform->waveparms[0];
8796                         waveparms[1] = deform->waveparms[1];
8797                         waveparms[2] = deform->waveparms[2];
8798                         waveparms[3] = deform->waveparms[3];
8799                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8800                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8801                         // this is how a divisor of vertex influence on deformation
8802                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8803                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8804 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8805 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8806 //                      rsurface.batchvertex3f_bufferoffset = 0;
8807 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8808 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8809 //                      rsurface.batchnormal3f_bufferoffset = 0;
8810                         for (j = 0;j < batchnumvertices;j++)
8811                         {
8812                                 // if the wavefunc depends on time, evaluate it per-vertex
8813                                 if (waveparms[3])
8814                                 {
8815                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8816                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8817                                 }
8818                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8819                         }
8820                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8821                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8822                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8823                         {
8824 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8825 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8826 //                              rsurface.batchsvector3f_bufferoffset = 0;
8827 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8828 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8829 //                              rsurface.batchtvector3f_bufferoffset = 0;
8830                                 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);
8831                         }
8832                         break;
8833                 case Q3DEFORM_BULGE:
8834                         // deform vertex array to make the surface have moving bulges
8835 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8836 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8837 //                      rsurface.batchvertex3f_bufferoffset = 0;
8838 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8839 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8840 //                      rsurface.batchnormal3f_bufferoffset = 0;
8841                         for (j = 0;j < batchnumvertices;j++)
8842                         {
8843                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8844                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8845                         }
8846                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8847                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8848                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8849                         {
8850 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8851 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8852 //                              rsurface.batchsvector3f_bufferoffset = 0;
8853 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8854 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8855 //                              rsurface.batchtvector3f_bufferoffset = 0;
8856                                 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);
8857                         }
8858                         break;
8859                 case Q3DEFORM_MOVE:
8860                         // deform vertex array
8861                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8862                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8863                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8864                         VectorScale(deform->parms, scale, waveparms);
8865 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8866 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8867 //                      rsurface.batchvertex3f_bufferoffset = 0;
8868                         for (j = 0;j < batchnumvertices;j++)
8869                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8870                         break;
8871                 }
8872         }
8873
8874         // generate texcoords based on the chosen texcoord source
8875         switch(rsurface.texture->tcgen.tcgen)
8876         {
8877         default:
8878         case Q3TCGEN_TEXTURE:
8879                 break;
8880         case Q3TCGEN_LIGHTMAP:
8881 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8882 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8883 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8884                 if (rsurface.batchtexcoordlightmap2f)
8885                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8886                 break;
8887         case Q3TCGEN_VECTOR:
8888 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8889 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8890 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8891                 for (j = 0;j < batchnumvertices;j++)
8892                 {
8893                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8894                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8895                 }
8896                 break;
8897         case Q3TCGEN_ENVIRONMENT:
8898                 // make environment reflections using a spheremap
8899                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8900                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8901                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8902                 for (j = 0;j < batchnumvertices;j++)
8903                 {
8904                         // identical to Q3A's method, but executed in worldspace so
8905                         // carried models can be shiny too
8906
8907                         float viewer[3], d, reflected[3], worldreflected[3];
8908
8909                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8910                         // VectorNormalize(viewer);
8911
8912                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8913
8914                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8915                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8916                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8917                         // note: this is proportinal to viewer, so we can normalize later
8918
8919                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8920                         VectorNormalize(worldreflected);
8921
8922                         // note: this sphere map only uses world x and z!
8923                         // so positive and negative y will LOOK THE SAME.
8924                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8925                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8926                 }
8927                 break;
8928         }
8929         // the only tcmod that needs software vertex processing is turbulent, so
8930         // check for it here and apply the changes if needed
8931         // and we only support that as the first one
8932         // (handling a mixture of turbulent and other tcmods would be problematic
8933         //  without punting it entirely to a software path)
8934         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8935         {
8936                 amplitude = rsurface.texture->tcmods[0].parms[1];
8937                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8938 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8939 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8940 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8941                 for (j = 0;j < batchnumvertices;j++)
8942                 {
8943                         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);
8944                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8945                 }
8946         }
8947
8948         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8949         {
8950                 // convert the modified arrays to vertex structs
8951 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8952 //              rsurface.batchvertexmeshbuffer = NULL;
8953                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8954                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8955                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8956                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8957                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8958                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8959                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8960                 {
8961                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8962                         {
8963                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8964                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8965                         }
8966                 }
8967                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8968                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8970                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8971                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8972                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8973                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8974                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8975                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8976         }
8977 }
8978
8979 void RSurf_DrawBatch(void)
8980 {
8981         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8982         // through the pipeline, killing it earlier in the pipeline would have
8983         // per-surface overhead rather than per-batch overhead, so it's best to
8984         // reject it here, before it hits glDraw.
8985         if (rsurface.batchnumtriangles == 0)
8986                 return;
8987 #if 0
8988         // batch debugging code
8989         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8990         {
8991                 int i;
8992                 int j;
8993                 int c;
8994                 const int *e;
8995                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8996                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8997                 {
8998                         c = e[i];
8999                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9000                         {
9001                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9002                                 {
9003                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9004                                                 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);
9005                                         break;
9006                                 }
9007                         }
9008                 }
9009         }
9010 #endif
9011         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);
9012 }
9013
9014 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9015 {
9016         // pick the closest matching water plane
9017         int planeindex, vertexindex, bestplaneindex = -1;
9018         float d, bestd;
9019         vec3_t vert;
9020         const float *v;
9021         r_waterstate_waterplane_t *p;
9022         qboolean prepared = false;
9023         bestd = 0;
9024         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9025         {
9026                 if(p->camera_entity != rsurface.texture->camera_entity)
9027                         continue;
9028                 d = 0;
9029                 if(!prepared)
9030                 {
9031                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9032                         prepared = true;
9033                         if(rsurface.batchnumvertices == 0)
9034                                 break;
9035                 }
9036                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9037                 {
9038                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9039                         d += fabs(PlaneDiff(vert, &p->plane));
9040                 }
9041                 if (bestd > d || bestplaneindex < 0)
9042                 {
9043                         bestd = d;
9044                         bestplaneindex = planeindex;
9045                 }
9046         }
9047         return bestplaneindex;
9048         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9049         // this situation though, as it might be better to render single larger
9050         // batches with useless stuff (backface culled for example) than to
9051         // render multiple smaller batches
9052 }
9053
9054 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9055 {
9056         int i;
9057         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9058         rsurface.passcolor4f_vertexbuffer = 0;
9059         rsurface.passcolor4f_bufferoffset = 0;
9060         for (i = 0;i < rsurface.batchnumvertices;i++)
9061                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9062 }
9063
9064 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9065 {
9066         int i;
9067         float f;
9068         const float *v;
9069         const float *c;
9070         float *c2;
9071         if (rsurface.passcolor4f)
9072         {
9073                 // generate color arrays
9074                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9075                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9076                 rsurface.passcolor4f_vertexbuffer = 0;
9077                 rsurface.passcolor4f_bufferoffset = 0;
9078                 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)
9079                 {
9080                         f = RSurf_FogVertex(v);
9081                         c2[0] = c[0] * f;
9082                         c2[1] = c[1] * f;
9083                         c2[2] = c[2] * f;
9084                         c2[3] = c[3];
9085                 }
9086         }
9087         else
9088         {
9089                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9090                 rsurface.passcolor4f_vertexbuffer = 0;
9091                 rsurface.passcolor4f_bufferoffset = 0;
9092                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9093                 {
9094                         f = RSurf_FogVertex(v);
9095                         c2[0] = f;
9096                         c2[1] = f;
9097                         c2[2] = f;
9098                         c2[3] = 1;
9099                 }
9100         }
9101 }
9102
9103 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9104 {
9105         int i;
9106         float f;
9107         const float *v;
9108         const float *c;
9109         float *c2;
9110         if (!rsurface.passcolor4f)
9111                 return;
9112         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9113         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9114         rsurface.passcolor4f_vertexbuffer = 0;
9115         rsurface.passcolor4f_bufferoffset = 0;
9116         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)
9117         {
9118                 f = RSurf_FogVertex(v);
9119                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9120                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9121                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9122                 c2[3] = c[3];
9123         }
9124 }
9125
9126 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9127 {
9128         int i;
9129         const float *c;
9130         float *c2;
9131         if (!rsurface.passcolor4f)
9132                 return;
9133         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9134         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9135         rsurface.passcolor4f_vertexbuffer = 0;
9136         rsurface.passcolor4f_bufferoffset = 0;
9137         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9138         {
9139                 c2[0] = c[0] * r;
9140                 c2[1] = c[1] * g;
9141                 c2[2] = c[2] * b;
9142                 c2[3] = c[3] * a;
9143         }
9144 }
9145
9146 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9147 {
9148         int i;
9149         const float *c;
9150         float *c2;
9151         if (!rsurface.passcolor4f)
9152                 return;
9153         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9154         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9155         rsurface.passcolor4f_vertexbuffer = 0;
9156         rsurface.passcolor4f_bufferoffset = 0;
9157         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9158         {
9159                 c2[0] = c[0] + r_refdef.scene.ambient;
9160                 c2[1] = c[1] + r_refdef.scene.ambient;
9161                 c2[2] = c[2] + r_refdef.scene.ambient;
9162                 c2[3] = c[3];
9163         }
9164 }
9165
9166 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9167 {
9168         // TODO: optimize
9169         rsurface.passcolor4f = NULL;
9170         rsurface.passcolor4f_vertexbuffer = 0;
9171         rsurface.passcolor4f_bufferoffset = 0;
9172         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9173         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9174         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9175         GL_Color(r, g, b, a);
9176         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9177         RSurf_DrawBatch();
9178 }
9179
9180 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9181 {
9182         // TODO: optimize applyfog && applycolor case
9183         // just apply fog if necessary, and tint the fog color array if necessary
9184         rsurface.passcolor4f = NULL;
9185         rsurface.passcolor4f_vertexbuffer = 0;
9186         rsurface.passcolor4f_bufferoffset = 0;
9187         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9188         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9189         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9190         GL_Color(r, g, b, a);
9191         RSurf_DrawBatch();
9192 }
9193
9194 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9195 {
9196         // TODO: optimize
9197         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9198         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9199         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9200         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9201         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9202         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9203         GL_Color(r, g, b, a);
9204         RSurf_DrawBatch();
9205 }
9206
9207 static void RSurf_DrawBatch_GL11_ClampColor(void)
9208 {
9209         int i;
9210         const float *c1;
9211         float *c2;
9212         if (!rsurface.passcolor4f)
9213                 return;
9214         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9215         {
9216                 c2[0] = bound(0.0f, c1[0], 1.0f);
9217                 c2[1] = bound(0.0f, c1[1], 1.0f);
9218                 c2[2] = bound(0.0f, c1[2], 1.0f);
9219                 c2[3] = bound(0.0f, c1[3], 1.0f);
9220         }
9221 }
9222
9223 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9224 {
9225         int i;
9226         float f;
9227         const float *v;
9228         const float *n;
9229         float *c;
9230         //vec3_t eyedir;
9231
9232         // fake shading
9233         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9234         rsurface.passcolor4f_vertexbuffer = 0;
9235         rsurface.passcolor4f_bufferoffset = 0;
9236         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)
9237         {
9238                 f = -DotProduct(r_refdef.view.forward, n);
9239                 f = max(0, f);
9240                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9241                 f *= r_refdef.lightmapintensity;
9242                 Vector4Set(c, f, f, f, 1);
9243         }
9244 }
9245
9246 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9247 {
9248         RSurf_DrawBatch_GL11_ApplyFakeLight();
9249         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9250         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9251         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9252         GL_Color(r, g, b, a);
9253         RSurf_DrawBatch();
9254 }
9255
9256 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9257 {
9258         int i;
9259         float f;
9260         float alpha;
9261         const float *v;
9262         const float *n;
9263         float *c;
9264         vec3_t ambientcolor;
9265         vec3_t diffusecolor;
9266         vec3_t lightdir;
9267         // TODO: optimize
9268         // model lighting
9269         VectorCopy(rsurface.modellight_lightdir, lightdir);
9270         f = 0.5f * r_refdef.lightmapintensity;
9271         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9272         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9273         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9274         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9275         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9276         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9277         alpha = *a;
9278         if (VectorLength2(diffusecolor) > 0)
9279         {
9280                 // q3-style directional shading
9281                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9282                 rsurface.passcolor4f_vertexbuffer = 0;
9283                 rsurface.passcolor4f_bufferoffset = 0;
9284                 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)
9285                 {
9286                         if ((f = DotProduct(n, lightdir)) > 0)
9287                                 VectorMA(ambientcolor, f, diffusecolor, c);
9288                         else
9289                                 VectorCopy(ambientcolor, c);
9290                         c[3] = alpha;
9291                 }
9292                 *r = 1;
9293                 *g = 1;
9294                 *b = 1;
9295                 *a = 1;
9296                 *applycolor = false;
9297         }
9298         else
9299         {
9300                 *r = ambientcolor[0];
9301                 *g = ambientcolor[1];
9302                 *b = ambientcolor[2];
9303                 rsurface.passcolor4f = NULL;
9304                 rsurface.passcolor4f_vertexbuffer = 0;
9305                 rsurface.passcolor4f_bufferoffset = 0;
9306         }
9307 }
9308
9309 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9310 {
9311         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9312         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9313         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9314         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9315         GL_Color(r, g, b, a);
9316         RSurf_DrawBatch();
9317 }
9318
9319 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9320 {
9321         int i;
9322         float f;
9323         const float *v;
9324         float *c;
9325
9326         // fake shading
9327         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9328         rsurface.passcolor4f_vertexbuffer = 0;
9329         rsurface.passcolor4f_bufferoffset = 0;
9330
9331         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9332         {
9333                 f = 1 - RSurf_FogVertex(v);
9334                 c[0] = r;
9335                 c[1] = g;
9336                 c[2] = b;
9337                 c[3] = f * a;
9338         }
9339 }
9340
9341 void RSurf_SetupDepthAndCulling(void)
9342 {
9343         // submodels are biased to avoid z-fighting with world surfaces that they
9344         // may be exactly overlapping (avoids z-fighting artifacts on certain
9345         // doors and things in Quake maps)
9346         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9347         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9348         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9349         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9350 }
9351
9352 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9353 {
9354         // transparent sky would be ridiculous
9355         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9356                 return;
9357         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9358         skyrenderlater = true;
9359         RSurf_SetupDepthAndCulling();
9360         GL_DepthMask(true);
9361         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9362         // skymasking on them, and Quake3 never did sky masking (unlike
9363         // software Quake and software Quake2), so disable the sky masking
9364         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9365         // and skymasking also looks very bad when noclipping outside the
9366         // level, so don't use it then either.
9367         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9368         {
9369                 R_Mesh_ResetTextureState();
9370                 if (skyrendermasked)
9371                 {
9372                         R_SetupShader_DepthOrShadow();
9373                         // depth-only (masking)
9374                         GL_ColorMask(0,0,0,0);
9375                         // just to make sure that braindead drivers don't draw
9376                         // anything despite that colormask...
9377                         GL_BlendFunc(GL_ZERO, GL_ONE);
9378                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9379                         if (rsurface.batchvertex3fbuffer)
9380                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9381                         else
9382                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9383                 }
9384                 else
9385                 {
9386                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9387                         // fog sky
9388                         GL_BlendFunc(GL_ONE, GL_ZERO);
9389                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9390                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9391                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9392                 }
9393                 RSurf_DrawBatch();
9394                 if (skyrendermasked)
9395                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9396         }
9397         R_Mesh_ResetTextureState();
9398         GL_Color(1, 1, 1, 1);
9399 }
9400
9401 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9402 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9403 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9404 {
9405         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9406                 return;
9407         if (prepass)
9408         {
9409                 // render screenspace normalmap to texture
9410                 GL_DepthMask(true);
9411                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9412                 RSurf_DrawBatch();
9413                 return;
9414         }
9415
9416         // bind lightmap texture
9417
9418         // water/refraction/reflection/camera surfaces have to be handled specially
9419         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9420         {
9421                 int start, end, startplaneindex;
9422                 for (start = 0;start < texturenumsurfaces;start = end)
9423                 {
9424                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9425                         if(startplaneindex < 0)
9426                         {
9427                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9428                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9429                                 end = start + 1;
9430                                 continue;
9431                         }
9432                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9433                                 ;
9434                         // now that we have a batch using the same planeindex, render it
9435                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9436                         {
9437                                 // render water or distortion background
9438                                 GL_DepthMask(true);
9439                                 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));
9440                                 RSurf_DrawBatch();
9441                                 // blend surface on top
9442                                 GL_DepthMask(false);
9443                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9444                                 RSurf_DrawBatch();
9445                         }
9446                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9447                         {
9448                                 // render surface with reflection texture as input
9449                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9450                                 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));
9451                                 RSurf_DrawBatch();
9452                         }
9453                 }
9454                 return;
9455         }
9456
9457         // render surface batch normally
9458         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9459         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9460         RSurf_DrawBatch();
9461 }
9462
9463 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9464 {
9465         // OpenGL 1.3 path - anything not completely ancient
9466         qboolean applycolor;
9467         qboolean applyfog;
9468         int layerindex;
9469         const texturelayer_t *layer;
9470         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);
9471         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9472
9473         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9474         {
9475                 vec4_t layercolor;
9476                 int layertexrgbscale;
9477                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9478                 {
9479                         if (layerindex == 0)
9480                                 GL_AlphaTest(true);
9481                         else
9482                         {
9483                                 GL_AlphaTest(false);
9484                                 GL_DepthFunc(GL_EQUAL);
9485                         }
9486                 }
9487                 GL_DepthMask(layer->depthmask && writedepth);
9488                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9489                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9490                 {
9491                         layertexrgbscale = 4;
9492                         VectorScale(layer->color, 0.25f, layercolor);
9493                 }
9494                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9495                 {
9496                         layertexrgbscale = 2;
9497                         VectorScale(layer->color, 0.5f, layercolor);
9498                 }
9499                 else
9500                 {
9501                         layertexrgbscale = 1;
9502                         VectorScale(layer->color, 1.0f, layercolor);
9503                 }
9504                 layercolor[3] = layer->color[3];
9505                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9506                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9507                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9508                 switch (layer->type)
9509                 {
9510                 case TEXTURELAYERTYPE_LITTEXTURE:
9511                         // single-pass lightmapped texture with 2x rgbscale
9512                         R_Mesh_TexBind(0, r_texture_white);
9513                         R_Mesh_TexMatrix(0, NULL);
9514                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9515                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9516                         R_Mesh_TexBind(1, layer->texture);
9517                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9518                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9519                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9520                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9521                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9522                         else if (FAKELIGHT_ENABLED)
9523                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9524                         else if (rsurface.uselightmaptexture)
9525                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9526                         else
9527                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9528                         break;
9529                 case TEXTURELAYERTYPE_TEXTURE:
9530                         // singletexture unlit texture with transparency support
9531                         R_Mesh_TexBind(0, layer->texture);
9532                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9533                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9534                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9535                         R_Mesh_TexBind(1, 0);
9536                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9537                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9538                         break;
9539                 case TEXTURELAYERTYPE_FOG:
9540                         // singletexture fogging
9541                         if (layer->texture)
9542                         {
9543                                 R_Mesh_TexBind(0, layer->texture);
9544                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9545                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9546                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9547                         }
9548                         else
9549                         {
9550                                 R_Mesh_TexBind(0, 0);
9551                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9552                         }
9553                         R_Mesh_TexBind(1, 0);
9554                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9555                         // generate a color array for the fog pass
9556                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9557                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9558                         RSurf_DrawBatch();
9559                         break;
9560                 default:
9561                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9562                 }
9563         }
9564         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9565         {
9566                 GL_DepthFunc(GL_LEQUAL);
9567                 GL_AlphaTest(false);
9568         }
9569 }
9570
9571 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9572 {
9573         // OpenGL 1.1 - crusty old voodoo path
9574         qboolean applyfog;
9575         int layerindex;
9576         const texturelayer_t *layer;
9577         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);
9578         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9579
9580         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9581         {
9582                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9583                 {
9584                         if (layerindex == 0)
9585                                 GL_AlphaTest(true);
9586                         else
9587                         {
9588                                 GL_AlphaTest(false);
9589                                 GL_DepthFunc(GL_EQUAL);
9590                         }
9591                 }
9592                 GL_DepthMask(layer->depthmask && writedepth);
9593                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9594                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9595                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9596                 switch (layer->type)
9597                 {
9598                 case TEXTURELAYERTYPE_LITTEXTURE:
9599                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9600                         {
9601                                 // two-pass lit texture with 2x rgbscale
9602                                 // first the lightmap pass
9603                                 R_Mesh_TexBind(0, r_texture_white);
9604                                 R_Mesh_TexMatrix(0, NULL);
9605                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9606                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9607                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9608                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9609                                 else if (FAKELIGHT_ENABLED)
9610                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9611                                 else if (rsurface.uselightmaptexture)
9612                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9613                                 else
9614                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9615                                 // then apply the texture to it
9616                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9617                                 R_Mesh_TexBind(0, layer->texture);
9618                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9619                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9620                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9621                                 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);
9622                         }
9623                         else
9624                         {
9625                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9626                                 R_Mesh_TexBind(0, layer->texture);
9627                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9628                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9629                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9630                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9631                                         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);
9632                                 else
9633                                         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);
9634                         }
9635                         break;
9636                 case TEXTURELAYERTYPE_TEXTURE:
9637                         // singletexture unlit texture with transparency support
9638                         R_Mesh_TexBind(0, layer->texture);
9639                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9640                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9641                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9642                         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);
9643                         break;
9644                 case TEXTURELAYERTYPE_FOG:
9645                         // singletexture fogging
9646                         if (layer->texture)
9647                         {
9648                                 R_Mesh_TexBind(0, layer->texture);
9649                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9650                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9651                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9652                         }
9653                         else
9654                         {
9655                                 R_Mesh_TexBind(0, 0);
9656                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9657                         }
9658                         // generate a color array for the fog pass
9659                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9660                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9661                         RSurf_DrawBatch();
9662                         break;
9663                 default:
9664                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9665                 }
9666         }
9667         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9668         {
9669                 GL_DepthFunc(GL_LEQUAL);
9670                 GL_AlphaTest(false);
9671         }
9672 }
9673
9674 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9675 {
9676         int vi;
9677         int j;
9678         r_vertexgeneric_t *batchvertex;
9679         float c[4];
9680
9681 //      R_Mesh_ResetTextureState();
9682         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9683
9684         if(rsurface.texture && rsurface.texture->currentskinframe)
9685         {
9686                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9687                 c[3] *= rsurface.texture->currentalpha;
9688         }
9689         else
9690         {
9691                 c[0] = 1;
9692                 c[1] = 0;
9693                 c[2] = 1;
9694                 c[3] = 1;
9695         }
9696
9697         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9698         {
9699                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9700                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9701                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9702         }
9703
9704         // brighten it up (as texture value 127 means "unlit")
9705         c[0] *= 2 * r_refdef.view.colorscale;
9706         c[1] *= 2 * r_refdef.view.colorscale;
9707         c[2] *= 2 * r_refdef.view.colorscale;
9708
9709         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9710                 c[3] *= r_wateralpha.value;
9711
9712         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9713         {
9714                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9715                 GL_DepthMask(false);
9716         }
9717         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9718         {
9719                 GL_BlendFunc(GL_ONE, GL_ONE);
9720                 GL_DepthMask(false);
9721         }
9722         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9723         {
9724                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9725                 GL_DepthMask(false);
9726         }
9727         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9728         {
9729                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9730                 GL_DepthMask(false);
9731         }
9732         else
9733         {
9734                 GL_BlendFunc(GL_ONE, GL_ZERO);
9735                 GL_DepthMask(writedepth);
9736         }
9737
9738         if (r_showsurfaces.integer == 3)
9739         {
9740                 rsurface.passcolor4f = NULL;
9741
9742                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9743                 {
9744                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9745
9746                         rsurface.passcolor4f = NULL;
9747                         rsurface.passcolor4f_vertexbuffer = 0;
9748                         rsurface.passcolor4f_bufferoffset = 0;
9749                 }
9750                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9751                 {
9752                         qboolean applycolor = true;
9753                         float one = 1.0;
9754
9755                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9756
9757                         r_refdef.lightmapintensity = 1;
9758                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9759                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9760                 }
9761                 else if (FAKELIGHT_ENABLED)
9762                 {
9763                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9764
9765                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9766                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9767                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9768                 }
9769                 else
9770                 {
9771                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9772
9773                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9774                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9775                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9776                 }
9777
9778                 if(!rsurface.passcolor4f)
9779                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9780
9781                 RSurf_DrawBatch_GL11_ApplyAmbient();
9782                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9783                 if(r_refdef.fogenabled)
9784                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9785                 RSurf_DrawBatch_GL11_ClampColor();
9786
9787                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9788                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9789                 RSurf_DrawBatch();
9790         }
9791         else if (!r_refdef.view.showdebug)
9792         {
9793                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9794                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9795                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9796                 {
9797                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9798                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9799                 }
9800                 R_Mesh_PrepareVertices_Generic_Unlock();
9801                 RSurf_DrawBatch();
9802         }
9803         else if (r_showsurfaces.integer == 4)
9804         {
9805                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9807                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9808                 {
9809                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9810                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9811                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9812                 }
9813                 R_Mesh_PrepareVertices_Generic_Unlock();
9814                 RSurf_DrawBatch();
9815         }
9816         else if (r_showsurfaces.integer == 2)
9817         {
9818                 const int *e;
9819                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9820                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9821                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9822                 {
9823                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9824                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9825                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9826                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9827                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9828                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9829                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9830                 }
9831                 R_Mesh_PrepareVertices_Generic_Unlock();
9832                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9833         }
9834         else
9835         {
9836                 int texturesurfaceindex;
9837                 int k;
9838                 const msurface_t *surface;
9839                 float surfacecolor4f[4];
9840                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9841                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9842                 vi = 0;
9843                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9844                 {
9845                         surface = texturesurfacelist[texturesurfaceindex];
9846                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9847                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9848                         for (j = 0;j < surface->num_vertices;j++)
9849                         {
9850                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9851                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9852                                 vi++;
9853                         }
9854                 }
9855                 R_Mesh_PrepareVertices_Generic_Unlock();
9856                 RSurf_DrawBatch();
9857         }
9858 }
9859
9860 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9861 {
9862         CHECKGLERROR
9863         RSurf_SetupDepthAndCulling();
9864         if (r_showsurfaces.integer)
9865         {
9866                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9867                 return;
9868         }
9869         switch (vid.renderpath)
9870         {
9871         case RENDERPATH_GL20:
9872         case RENDERPATH_D3D9:
9873         case RENDERPATH_D3D10:
9874         case RENDERPATH_D3D11:
9875         case RENDERPATH_SOFT:
9876         case RENDERPATH_GLES2:
9877                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9878                 break;
9879         case RENDERPATH_GL13:
9880                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9881                 break;
9882         case RENDERPATH_GL11:
9883                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9884                 break;
9885         }
9886         CHECKGLERROR
9887 }
9888
9889 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9890 {
9891         CHECKGLERROR
9892         RSurf_SetupDepthAndCulling();
9893         if (r_showsurfaces.integer)
9894         {
9895                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9896                 return;
9897         }
9898         switch (vid.renderpath)
9899         {
9900         case RENDERPATH_GL20:
9901         case RENDERPATH_D3D9:
9902         case RENDERPATH_D3D10:
9903         case RENDERPATH_D3D11:
9904         case RENDERPATH_SOFT:
9905         case RENDERPATH_GLES2:
9906                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9907                 break;
9908         case RENDERPATH_GL13:
9909                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9910                 break;
9911         case RENDERPATH_GL11:
9912                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9913                 break;
9914         }
9915         CHECKGLERROR
9916 }
9917
9918 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9919 {
9920         int i, j;
9921         int texturenumsurfaces, endsurface;
9922         texture_t *texture;
9923         const msurface_t *surface;
9924 #define MAXBATCH_TRANSPARENTSURFACES 256
9925         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9926
9927         // if the model is static it doesn't matter what value we give for
9928         // wantnormals and wanttangents, so this logic uses only rules applicable
9929         // to a model, knowing that they are meaningless otherwise
9930         if (ent == r_refdef.scene.worldentity)
9931                 RSurf_ActiveWorldEntity();
9932         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9933                 RSurf_ActiveModelEntity(ent, false, false, false);
9934         else
9935         {
9936                 switch (vid.renderpath)
9937                 {
9938                 case RENDERPATH_GL20:
9939                 case RENDERPATH_D3D9:
9940                 case RENDERPATH_D3D10:
9941                 case RENDERPATH_D3D11:
9942                 case RENDERPATH_SOFT:
9943                 case RENDERPATH_GLES2:
9944                         RSurf_ActiveModelEntity(ent, true, true, false);
9945                         break;
9946                 case RENDERPATH_GL13:
9947                 case RENDERPATH_GL11:
9948                         RSurf_ActiveModelEntity(ent, true, false, false);
9949                         break;
9950                 }
9951         }
9952
9953         if (r_transparentdepthmasking.integer)
9954         {
9955                 qboolean setup = false;
9956                 for (i = 0;i < numsurfaces;i = j)
9957                 {
9958                         j = i + 1;
9959                         surface = rsurface.modelsurfaces + surfacelist[i];
9960                         texture = surface->texture;
9961                         rsurface.texture = R_GetCurrentTexture(texture);
9962                         rsurface.lightmaptexture = NULL;
9963                         rsurface.deluxemaptexture = NULL;
9964                         rsurface.uselightmaptexture = false;
9965                         // scan ahead until we find a different texture
9966                         endsurface = min(i + 1024, numsurfaces);
9967                         texturenumsurfaces = 0;
9968                         texturesurfacelist[texturenumsurfaces++] = surface;
9969                         for (;j < endsurface;j++)
9970                         {
9971                                 surface = rsurface.modelsurfaces + surfacelist[j];
9972                                 if (texture != surface->texture)
9973                                         break;
9974                                 texturesurfacelist[texturenumsurfaces++] = surface;
9975                         }
9976                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9977                                 continue;
9978                         // render the range of surfaces as depth
9979                         if (!setup)
9980                         {
9981                                 setup = true;
9982                                 GL_ColorMask(0,0,0,0);
9983                                 GL_Color(1,1,1,1);
9984                                 GL_DepthTest(true);
9985                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9986                                 GL_DepthMask(true);
9987 //                              R_Mesh_ResetTextureState();
9988                                 R_SetupShader_DepthOrShadow();
9989                         }
9990                         RSurf_SetupDepthAndCulling();
9991                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9992                         if (rsurface.batchvertex3fbuffer)
9993                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9994                         else
9995                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9996                         RSurf_DrawBatch();
9997                 }
9998                 if (setup)
9999                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10000         }
10001
10002         for (i = 0;i < numsurfaces;i = j)
10003         {
10004                 j = i + 1;
10005                 surface = rsurface.modelsurfaces + surfacelist[i];
10006                 texture = surface->texture;
10007                 rsurface.texture = R_GetCurrentTexture(texture);
10008                 // scan ahead until we find a different texture
10009                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10010                 texturenumsurfaces = 0;
10011                 texturesurfacelist[texturenumsurfaces++] = surface;
10012                 if(FAKELIGHT_ENABLED)
10013                 {
10014                         rsurface.lightmaptexture = NULL;
10015                         rsurface.deluxemaptexture = NULL;
10016                         rsurface.uselightmaptexture = false;
10017                         for (;j < endsurface;j++)
10018                         {
10019                                 surface = rsurface.modelsurfaces + surfacelist[j];
10020                                 if (texture != surface->texture)
10021                                         break;
10022                                 texturesurfacelist[texturenumsurfaces++] = surface;
10023                         }
10024                 }
10025                 else
10026                 {
10027                         rsurface.lightmaptexture = surface->lightmaptexture;
10028                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10029                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10030                         for (;j < endsurface;j++)
10031                         {
10032                                 surface = rsurface.modelsurfaces + surfacelist[j];
10033                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10034                                         break;
10035                                 texturesurfacelist[texturenumsurfaces++] = surface;
10036                         }
10037                 }
10038                 // render the range of surfaces
10039                 if (ent == r_refdef.scene.worldentity)
10040                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10041                 else
10042                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10043         }
10044         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10045 }
10046
10047 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10048 {
10049         // transparent surfaces get pushed off into the transparent queue
10050         int surfacelistindex;
10051         const msurface_t *surface;
10052         vec3_t tempcenter, center;
10053         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10054         {
10055                 surface = texturesurfacelist[surfacelistindex];
10056                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10057                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10058                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10059                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10060                 if (queueentity->transparent_offset) // transparent offset
10061                 {
10062                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10063                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10064                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10065                 }
10066                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10067         }
10068 }
10069
10070 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10071 {
10072         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10073                 return;
10074         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10075                 return;
10076         RSurf_SetupDepthAndCulling();
10077         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10078         if (rsurface.batchvertex3fbuffer)
10079                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10080         else
10081                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10082         RSurf_DrawBatch();
10083 }
10084
10085 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10086 {
10087         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10088         CHECKGLERROR
10089         if (depthonly)
10090                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10091         else if (prepass)
10092         {
10093                 if (!rsurface.texture->currentnumlayers)
10094                         return;
10095                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10096                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10097                 else
10098                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10099         }
10100         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10101                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10102         else if (!rsurface.texture->currentnumlayers)
10103                 return;
10104         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10105         {
10106                 // in the deferred case, transparent surfaces were queued during prepass
10107                 if (!r_shadow_usingdeferredprepass)
10108                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10109         }
10110         else
10111         {
10112                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10113                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10114         }
10115         CHECKGLERROR
10116 }
10117
10118 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10119 {
10120         int i, j;
10121         texture_t *texture;
10122         R_FrameData_SetMark();
10123         // break the surface list down into batches by texture and use of lightmapping
10124         for (i = 0;i < numsurfaces;i = j)
10125         {
10126                 j = i + 1;
10127                 // texture is the base texture pointer, rsurface.texture is the
10128                 // current frame/skin the texture is directing us to use (for example
10129                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10130                 // use skin 1 instead)
10131                 texture = surfacelist[i]->texture;
10132                 rsurface.texture = R_GetCurrentTexture(texture);
10133                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10134                 {
10135                         // if this texture is not the kind we want, skip ahead to the next one
10136                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10137                                 ;
10138                         continue;
10139                 }
10140                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10141                 {
10142                         rsurface.lightmaptexture = NULL;
10143                         rsurface.deluxemaptexture = NULL;
10144                         rsurface.uselightmaptexture = false;
10145                         // simply scan ahead until we find a different texture or lightmap state
10146                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10147                                 ;
10148                 }
10149                 else
10150                 {
10151                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10152                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10153                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10154                         // simply scan ahead until we find a different texture or lightmap state
10155                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10156                                 ;
10157                 }
10158                 // render the range of surfaces
10159                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10160         }
10161         R_FrameData_ReturnToMark();
10162 }
10163
10164 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10165 {
10166         CHECKGLERROR
10167         if (depthonly)
10168                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10169         else if (prepass)
10170         {
10171                 if (!rsurface.texture->currentnumlayers)
10172                         return;
10173                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10174                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10175                 else
10176                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10177         }
10178         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10179                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10180         else if (!rsurface.texture->currentnumlayers)
10181                 return;
10182         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10183         {
10184                 // in the deferred case, transparent surfaces were queued during prepass
10185                 if (!r_shadow_usingdeferredprepass)
10186                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10187         }
10188         else
10189         {
10190                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10191                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10192         }
10193         CHECKGLERROR
10194 }
10195
10196 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10197 {
10198         int i, j;
10199         texture_t *texture;
10200         R_FrameData_SetMark();
10201         // break the surface list down into batches by texture and use of lightmapping
10202         for (i = 0;i < numsurfaces;i = j)
10203         {
10204                 j = i + 1;
10205                 // texture is the base texture pointer, rsurface.texture is the
10206                 // current frame/skin the texture is directing us to use (for example
10207                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10208                 // use skin 1 instead)
10209                 texture = surfacelist[i]->texture;
10210                 rsurface.texture = R_GetCurrentTexture(texture);
10211                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10212                 {
10213                         // if this texture is not the kind we want, skip ahead to the next one
10214                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10215                                 ;
10216                         continue;
10217                 }
10218                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10219                 {
10220                         rsurface.lightmaptexture = NULL;
10221                         rsurface.deluxemaptexture = NULL;
10222                         rsurface.uselightmaptexture = false;
10223                         // simply scan ahead until we find a different texture or lightmap state
10224                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10225                                 ;
10226                 }
10227                 else
10228                 {
10229                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10230                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10231                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10232                         // simply scan ahead until we find a different texture or lightmap state
10233                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10234                                 ;
10235                 }
10236                 // render the range of surfaces
10237                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10238         }
10239         R_FrameData_ReturnToMark();
10240 }
10241
10242 float locboxvertex3f[6*4*3] =
10243 {
10244         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10245         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10246         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10247         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10248         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10249         1,0,0, 0,0,0, 0,1,0, 1,1,0
10250 };
10251
10252 unsigned short locboxelements[6*2*3] =
10253 {
10254          0, 1, 2, 0, 2, 3,
10255          4, 5, 6, 4, 6, 7,
10256          8, 9,10, 8,10,11,
10257         12,13,14, 12,14,15,
10258         16,17,18, 16,18,19,
10259         20,21,22, 20,22,23
10260 };
10261
10262 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10263 {
10264         int i, j;
10265         cl_locnode_t *loc = (cl_locnode_t *)ent;
10266         vec3_t mins, size;
10267         float vertex3f[6*4*3];
10268         CHECKGLERROR
10269         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10270         GL_DepthMask(false);
10271         GL_DepthRange(0, 1);
10272         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10273         GL_DepthTest(true);
10274         GL_CullFace(GL_NONE);
10275         R_EntityMatrix(&identitymatrix);
10276
10277 //      R_Mesh_ResetTextureState();
10278
10279         i = surfacelist[0];
10280         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10281                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10282                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10283                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10284
10285         if (VectorCompare(loc->mins, loc->maxs))
10286         {
10287                 VectorSet(size, 2, 2, 2);
10288                 VectorMA(loc->mins, -0.5f, size, mins);
10289         }
10290         else
10291         {
10292                 VectorCopy(loc->mins, mins);
10293                 VectorSubtract(loc->maxs, loc->mins, size);
10294         }
10295
10296         for (i = 0;i < 6*4*3;)
10297                 for (j = 0;j < 3;j++, i++)
10298                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10299
10300         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10301         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10302         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10303 }
10304
10305 void R_DrawLocs(void)
10306 {
10307         int index;
10308         cl_locnode_t *loc, *nearestloc;
10309         vec3_t center;
10310         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10311         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10312         {
10313                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10314                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10315         }
10316 }
10317
10318 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10319 {
10320         if (decalsystem->decals)
10321                 Mem_Free(decalsystem->decals);
10322         memset(decalsystem, 0, sizeof(*decalsystem));
10323 }
10324
10325 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)
10326 {
10327         tridecal_t *decal;
10328         tridecal_t *decals;
10329         int i;
10330
10331         // expand or initialize the system
10332         if (decalsystem->maxdecals <= decalsystem->numdecals)
10333         {
10334                 decalsystem_t old = *decalsystem;
10335                 qboolean useshortelements;
10336                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10337                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10338                 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)));
10339                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10340                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10341                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10342                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10343                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10344                 if (decalsystem->numdecals)
10345                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10346                 if (old.decals)
10347                         Mem_Free(old.decals);
10348                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10349                         decalsystem->element3i[i] = i;
10350                 if (useshortelements)
10351                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10352                                 decalsystem->element3s[i] = i;
10353         }
10354
10355         // grab a decal and search for another free slot for the next one
10356         decals = decalsystem->decals;
10357         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10358         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10359                 ;
10360         decalsystem->freedecal = i;
10361         if (decalsystem->numdecals <= i)
10362                 decalsystem->numdecals = i + 1;
10363
10364         // initialize the decal
10365         decal->lived = 0;
10366         decal->triangleindex = triangleindex;
10367         decal->surfaceindex = surfaceindex;
10368         decal->decalsequence = decalsequence;
10369         decal->color4f[0][0] = c0[0];
10370         decal->color4f[0][1] = c0[1];
10371         decal->color4f[0][2] = c0[2];
10372         decal->color4f[0][3] = 1;
10373         decal->color4f[1][0] = c1[0];
10374         decal->color4f[1][1] = c1[1];
10375         decal->color4f[1][2] = c1[2];
10376         decal->color4f[1][3] = 1;
10377         decal->color4f[2][0] = c2[0];
10378         decal->color4f[2][1] = c2[1];
10379         decal->color4f[2][2] = c2[2];
10380         decal->color4f[2][3] = 1;
10381         decal->vertex3f[0][0] = v0[0];
10382         decal->vertex3f[0][1] = v0[1];
10383         decal->vertex3f[0][2] = v0[2];
10384         decal->vertex3f[1][0] = v1[0];
10385         decal->vertex3f[1][1] = v1[1];
10386         decal->vertex3f[1][2] = v1[2];
10387         decal->vertex3f[2][0] = v2[0];
10388         decal->vertex3f[2][1] = v2[1];
10389         decal->vertex3f[2][2] = v2[2];
10390         decal->texcoord2f[0][0] = t0[0];
10391         decal->texcoord2f[0][1] = t0[1];
10392         decal->texcoord2f[1][0] = t1[0];
10393         decal->texcoord2f[1][1] = t1[1];
10394         decal->texcoord2f[2][0] = t2[0];
10395         decal->texcoord2f[2][1] = t2[1];
10396 }
10397
10398 extern cvar_t cl_decals_bias;
10399 extern cvar_t cl_decals_models;
10400 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10401 // baseparms, parms, temps
10402 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)
10403 {
10404         int cornerindex;
10405         int index;
10406         float v[9][3];
10407         const float *vertex3f;
10408         const float *normal3f;
10409         int numpoints;
10410         float points[2][9][3];
10411         float temp[3];
10412         float tc[9][2];
10413         float f;
10414         float c[9][4];
10415         const int *e;
10416
10417         e = rsurface.modelelement3i + 3*triangleindex;
10418
10419         vertex3f = rsurface.modelvertex3f;
10420         normal3f = rsurface.modelnormal3f;
10421
10422         if (normal3f)
10423         {
10424                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10425                 {
10426                         index = 3*e[cornerindex];
10427                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10428                 }
10429         }
10430         else
10431         {
10432                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10433                 {
10434                         index = 3*e[cornerindex];
10435                         VectorCopy(vertex3f + index, v[cornerindex]);
10436                 }
10437         }
10438
10439         // cull backfaces
10440         //TriangleNormal(v[0], v[1], v[2], normal);
10441         //if (DotProduct(normal, localnormal) < 0.0f)
10442         //      continue;
10443         // clip by each of the box planes formed from the projection matrix
10444         // if anything survives, we emit the decal
10445         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]);
10446         if (numpoints < 3)
10447                 return;
10448         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]);
10449         if (numpoints < 3)
10450                 return;
10451         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]);
10452         if (numpoints < 3)
10453                 return;
10454         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]);
10455         if (numpoints < 3)
10456                 return;
10457         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]);
10458         if (numpoints < 3)
10459                 return;
10460         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]);
10461         if (numpoints < 3)
10462                 return;
10463         // some part of the triangle survived, so we have to accept it...
10464         if (dynamic)
10465         {
10466                 // dynamic always uses the original triangle
10467                 numpoints = 3;
10468                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10469                 {
10470                         index = 3*e[cornerindex];
10471                         VectorCopy(vertex3f + index, v[cornerindex]);
10472                 }
10473         }
10474         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10475         {
10476                 // convert vertex positions to texcoords
10477                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10478                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10479                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10480                 // calculate distance fade from the projection origin
10481                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10482                 f = bound(0.0f, f, 1.0f);
10483                 c[cornerindex][0] = r * f;
10484                 c[cornerindex][1] = g * f;
10485                 c[cornerindex][2] = b * f;
10486                 c[cornerindex][3] = 1.0f;
10487                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10488         }
10489         if (dynamic)
10490                 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);
10491         else
10492                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10493                         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);
10494 }
10495 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)
10496 {
10497         matrix4x4_t projection;
10498         decalsystem_t *decalsystem;
10499         qboolean dynamic;
10500         dp_model_t *model;
10501         const msurface_t *surface;
10502         const msurface_t *surfaces;
10503         const int *surfacelist;
10504         const texture_t *texture;
10505         int numtriangles;
10506         int numsurfacelist;
10507         int surfacelistindex;
10508         int surfaceindex;
10509         int triangleindex;
10510         float localorigin[3];
10511         float localnormal[3];
10512         float localmins[3];
10513         float localmaxs[3];
10514         float localsize;
10515         //float normal[3];
10516         float planes[6][4];
10517         float angles[3];
10518         bih_t *bih;
10519         int bih_triangles_count;
10520         int bih_triangles[256];
10521         int bih_surfaces[256];
10522
10523         decalsystem = &ent->decalsystem;
10524         model = ent->model;
10525         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10526         {
10527                 R_DecalSystem_Reset(&ent->decalsystem);
10528                 return;
10529         }
10530
10531         if (!model->brush.data_leafs && !cl_decals_models.integer)
10532         {
10533                 if (decalsystem->model)
10534                         R_DecalSystem_Reset(decalsystem);
10535                 return;
10536         }
10537
10538         if (decalsystem->model != model)
10539                 R_DecalSystem_Reset(decalsystem);
10540         decalsystem->model = model;
10541
10542         RSurf_ActiveModelEntity(ent, true, false, false);
10543
10544         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10545         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10546         VectorNormalize(localnormal);
10547         localsize = worldsize*rsurface.inversematrixscale;
10548         localmins[0] = localorigin[0] - localsize;
10549         localmins[1] = localorigin[1] - localsize;
10550         localmins[2] = localorigin[2] - localsize;
10551         localmaxs[0] = localorigin[0] + localsize;
10552         localmaxs[1] = localorigin[1] + localsize;
10553         localmaxs[2] = localorigin[2] + localsize;
10554
10555         //VectorCopy(localnormal, planes[4]);
10556         //VectorVectors(planes[4], planes[2], planes[0]);
10557         AnglesFromVectors(angles, localnormal, NULL, false);
10558         AngleVectors(angles, planes[0], planes[2], planes[4]);
10559         VectorNegate(planes[0], planes[1]);
10560         VectorNegate(planes[2], planes[3]);
10561         VectorNegate(planes[4], planes[5]);
10562         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10563         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10564         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10565         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10566         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10567         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10568
10569 #if 1
10570 // works
10571 {
10572         matrix4x4_t forwardprojection;
10573         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10574         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10575 }
10576 #else
10577 // broken
10578 {
10579         float projectionvector[4][3];
10580         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10581         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10582         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10583         projectionvector[0][0] = planes[0][0] * ilocalsize;
10584         projectionvector[0][1] = planes[1][0] * ilocalsize;
10585         projectionvector[0][2] = planes[2][0] * ilocalsize;
10586         projectionvector[1][0] = planes[0][1] * ilocalsize;
10587         projectionvector[1][1] = planes[1][1] * ilocalsize;
10588         projectionvector[1][2] = planes[2][1] * ilocalsize;
10589         projectionvector[2][0] = planes[0][2] * ilocalsize;
10590         projectionvector[2][1] = planes[1][2] * ilocalsize;
10591         projectionvector[2][2] = planes[2][2] * ilocalsize;
10592         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10593         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10594         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10595         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10596 }
10597 #endif
10598
10599         dynamic = model->surfmesh.isanimated;
10600         numsurfacelist = model->nummodelsurfaces;
10601         surfacelist = model->sortedmodelsurfaces;
10602         surfaces = model->data_surfaces;
10603
10604         bih = NULL;
10605         bih_triangles_count = -1;
10606         if(!dynamic)
10607         {
10608                 if(model->render_bih.numleafs)
10609                         bih = &model->render_bih;
10610                 else if(model->collision_bih.numleafs)
10611                         bih = &model->collision_bih;
10612         }
10613         if(bih)
10614                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10615         if(bih_triangles_count == 0)
10616                 return;
10617         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10618                 return;
10619         if(bih_triangles_count > 0)
10620         {
10621                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10622                 {
10623                         surfaceindex = bih_surfaces[triangleindex];
10624                         surface = surfaces + surfaceindex;
10625                         texture = surface->texture;
10626                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10627                                 continue;
10628                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10629                                 continue;
10630                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10631                 }
10632         }
10633         else
10634         {
10635                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10636                 {
10637                         surfaceindex = surfacelist[surfacelistindex];
10638                         surface = surfaces + surfaceindex;
10639                         // check cull box first because it rejects more than any other check
10640                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10641                                 continue;
10642                         // skip transparent surfaces
10643                         texture = surface->texture;
10644                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10645                                 continue;
10646                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10647                                 continue;
10648                         numtriangles = surface->num_triangles;
10649                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10650                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10651                 }
10652         }
10653 }
10654
10655 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10656 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)
10657 {
10658         int renderentityindex;
10659         float worldmins[3];
10660         float worldmaxs[3];
10661         entity_render_t *ent;
10662
10663         if (!cl_decals_newsystem.integer)
10664                 return;
10665
10666         worldmins[0] = worldorigin[0] - worldsize;
10667         worldmins[1] = worldorigin[1] - worldsize;
10668         worldmins[2] = worldorigin[2] - worldsize;
10669         worldmaxs[0] = worldorigin[0] + worldsize;
10670         worldmaxs[1] = worldorigin[1] + worldsize;
10671         worldmaxs[2] = worldorigin[2] + worldsize;
10672
10673         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10674
10675         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10676         {
10677                 ent = r_refdef.scene.entities[renderentityindex];
10678                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10679                         continue;
10680
10681                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10682         }
10683 }
10684
10685 typedef struct r_decalsystem_splatqueue_s
10686 {
10687         vec3_t worldorigin;
10688         vec3_t worldnormal;
10689         float color[4];
10690         float tcrange[4];
10691         float worldsize;
10692         int decalsequence;
10693 }
10694 r_decalsystem_splatqueue_t;
10695
10696 int r_decalsystem_numqueued = 0;
10697 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10698
10699 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)
10700 {
10701         r_decalsystem_splatqueue_t *queue;
10702
10703         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10704                 return;
10705
10706         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10707         VectorCopy(worldorigin, queue->worldorigin);
10708         VectorCopy(worldnormal, queue->worldnormal);
10709         Vector4Set(queue->color, r, g, b, a);
10710         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10711         queue->worldsize = worldsize;
10712         queue->decalsequence = cl.decalsequence++;
10713 }
10714
10715 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10716 {
10717         int i;
10718         r_decalsystem_splatqueue_t *queue;
10719
10720         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10721                 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);
10722         r_decalsystem_numqueued = 0;
10723 }
10724
10725 extern cvar_t cl_decals_max;
10726 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10727 {
10728         int i;
10729         decalsystem_t *decalsystem = &ent->decalsystem;
10730         int numdecals;
10731         int killsequence;
10732         tridecal_t *decal;
10733         float frametime;
10734         float lifetime;
10735
10736         if (!decalsystem->numdecals)
10737                 return;
10738
10739         if (r_showsurfaces.integer)
10740                 return;
10741
10742         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10743         {
10744                 R_DecalSystem_Reset(decalsystem);
10745                 return;
10746         }
10747
10748         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10749         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10750
10751         if (decalsystem->lastupdatetime)
10752                 frametime = (cl.time - decalsystem->lastupdatetime);
10753         else
10754                 frametime = 0;
10755         decalsystem->lastupdatetime = cl.time;
10756         decal = decalsystem->decals;
10757         numdecals = decalsystem->numdecals;
10758
10759         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10760         {
10761                 if (decal->color4f[0][3])
10762                 {
10763                         decal->lived += frametime;
10764                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10765                         {
10766                                 memset(decal, 0, sizeof(*decal));
10767                                 if (decalsystem->freedecal > i)
10768                                         decalsystem->freedecal = i;
10769                         }
10770                 }
10771         }
10772         decal = decalsystem->decals;
10773         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10774                 numdecals--;
10775
10776         // collapse the array by shuffling the tail decals into the gaps
10777         for (;;)
10778         {
10779                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10780                         decalsystem->freedecal++;
10781                 if (decalsystem->freedecal == numdecals)
10782                         break;
10783                 decal[decalsystem->freedecal] = decal[--numdecals];
10784         }
10785
10786         decalsystem->numdecals = numdecals;
10787
10788         if (numdecals <= 0)
10789         {
10790                 // if there are no decals left, reset decalsystem
10791                 R_DecalSystem_Reset(decalsystem);
10792         }
10793 }
10794
10795 extern skinframe_t *decalskinframe;
10796 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10797 {
10798         int i;
10799         decalsystem_t *decalsystem = &ent->decalsystem;
10800         int numdecals;
10801         tridecal_t *decal;
10802         float faderate;
10803         float alpha;
10804         float *v3f;
10805         float *c4f;
10806         float *t2f;
10807         const int *e;
10808         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10809         int numtris = 0;
10810
10811         numdecals = decalsystem->numdecals;
10812         if (!numdecals)
10813                 return;
10814
10815         if (r_showsurfaces.integer)
10816                 return;
10817
10818         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10819         {
10820                 R_DecalSystem_Reset(decalsystem);
10821                 return;
10822         }
10823
10824         // if the model is static it doesn't matter what value we give for
10825         // wantnormals and wanttangents, so this logic uses only rules applicable
10826         // to a model, knowing that they are meaningless otherwise
10827         if (ent == r_refdef.scene.worldentity)
10828                 RSurf_ActiveWorldEntity();
10829         else
10830                 RSurf_ActiveModelEntity(ent, false, false, false);
10831
10832         decalsystem->lastupdatetime = cl.time;
10833         decal = decalsystem->decals;
10834
10835         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10836
10837         // update vertex positions for animated models
10838         v3f = decalsystem->vertex3f;
10839         c4f = decalsystem->color4f;
10840         t2f = decalsystem->texcoord2f;
10841         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10842         {
10843                 if (!decal->color4f[0][3])
10844                         continue;
10845
10846                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10847                         continue;
10848
10849                 // update color values for fading decals
10850                 if (decal->lived >= cl_decals_time.value)
10851                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10852                 else
10853                         alpha = 1.0f;
10854
10855                 c4f[ 0] = decal->color4f[0][0] * alpha;
10856                 c4f[ 1] = decal->color4f[0][1] * alpha;
10857                 c4f[ 2] = decal->color4f[0][2] * alpha;
10858                 c4f[ 3] = 1;
10859                 c4f[ 4] = decal->color4f[1][0] * alpha;
10860                 c4f[ 5] = decal->color4f[1][1] * alpha;
10861                 c4f[ 6] = decal->color4f[1][2] * alpha;
10862                 c4f[ 7] = 1;
10863                 c4f[ 8] = decal->color4f[2][0] * alpha;
10864                 c4f[ 9] = decal->color4f[2][1] * alpha;
10865                 c4f[10] = decal->color4f[2][2] * alpha;
10866                 c4f[11] = 1;
10867
10868                 t2f[0] = decal->texcoord2f[0][0];
10869                 t2f[1] = decal->texcoord2f[0][1];
10870                 t2f[2] = decal->texcoord2f[1][0];
10871                 t2f[3] = decal->texcoord2f[1][1];
10872                 t2f[4] = decal->texcoord2f[2][0];
10873                 t2f[5] = decal->texcoord2f[2][1];
10874
10875                 // update vertex positions for animated models
10876                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10877                 {
10878                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10879                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10880                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10881                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10882                 }
10883                 else
10884                 {
10885                         VectorCopy(decal->vertex3f[0], v3f);
10886                         VectorCopy(decal->vertex3f[1], v3f + 3);
10887                         VectorCopy(decal->vertex3f[2], v3f + 6);
10888                 }
10889
10890                 if (r_refdef.fogenabled)
10891                 {
10892                         alpha = RSurf_FogVertex(v3f);
10893                         VectorScale(c4f, alpha, c4f);
10894                         alpha = RSurf_FogVertex(v3f + 3);
10895                         VectorScale(c4f + 4, alpha, c4f + 4);
10896                         alpha = RSurf_FogVertex(v3f + 6);
10897                         VectorScale(c4f + 8, alpha, c4f + 8);
10898                 }
10899
10900                 v3f += 9;
10901                 c4f += 12;
10902                 t2f += 6;
10903                 numtris++;
10904         }
10905
10906         if (numtris > 0)
10907         {
10908                 r_refdef.stats.drawndecals += numtris;
10909
10910                 // now render the decals all at once
10911                 // (this assumes they all use one particle font texture!)
10912                 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);
10913 //              R_Mesh_ResetTextureState();
10914                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10915                 GL_DepthMask(false);
10916                 GL_DepthRange(0, 1);
10917                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10918                 GL_DepthTest(true);
10919                 GL_CullFace(GL_NONE);
10920                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10921                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10922                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10923         }
10924 }
10925
10926 static void R_DrawModelDecals(void)
10927 {
10928         int i, numdecals;
10929
10930         // fade faster when there are too many decals
10931         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10932         for (i = 0;i < r_refdef.scene.numentities;i++)
10933                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10934
10935         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10936         for (i = 0;i < r_refdef.scene.numentities;i++)
10937                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10938                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10939
10940         R_DecalSystem_ApplySplatEntitiesQueue();
10941
10942         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10943         for (i = 0;i < r_refdef.scene.numentities;i++)
10944                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10945
10946         r_refdef.stats.totaldecals += numdecals;
10947
10948         if (r_showsurfaces.integer)
10949                 return;
10950
10951         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10952
10953         for (i = 0;i < r_refdef.scene.numentities;i++)
10954         {
10955                 if (!r_refdef.viewcache.entityvisible[i])
10956                         continue;
10957                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10958                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10959         }
10960 }
10961
10962 extern cvar_t mod_collision_bih;
10963 void R_DrawDebugModel(void)
10964 {
10965         entity_render_t *ent = rsurface.entity;
10966         int i, j, k, l, flagsmask;
10967         const msurface_t *surface;
10968         dp_model_t *model = ent->model;
10969         vec3_t v;
10970
10971         switch(vid.renderpath)
10972         {
10973         case RENDERPATH_GL11:
10974         case RENDERPATH_GL13:
10975         case RENDERPATH_GL20:
10976                 break;
10977         case RENDERPATH_D3D9:
10978                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10979                 return;
10980         case RENDERPATH_D3D10:
10981                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10982                 return;
10983         case RENDERPATH_D3D11:
10984                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10985                 return;
10986         case RENDERPATH_SOFT:
10987                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10988                 return;
10989         case RENDERPATH_GLES2:
10990                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10991                 return;
10992         }
10993
10994         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10995
10996 //      R_Mesh_ResetTextureState();
10997         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10998         GL_DepthRange(0, 1);
10999         GL_DepthTest(!r_showdisabledepthtest.integer);
11000         GL_DepthMask(false);
11001         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11002
11003         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11004         {
11005                 int triangleindex;
11006                 int bihleafindex;
11007                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11008                 const q3mbrush_t *brush;
11009                 const bih_t *bih = &model->collision_bih;
11010                 const bih_leaf_t *bihleaf;
11011                 float vertex3f[3][3];
11012                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11013                 cullbox = false;
11014                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11015                 {
11016                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11017                                 continue;
11018                         switch (bihleaf->type)
11019                         {
11020                         case BIH_BRUSH:
11021                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11022                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11023                                 {
11024                                         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);
11025                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11026                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11027                                 }
11028                                 break;
11029                         case BIH_COLLISIONTRIANGLE:
11030                                 triangleindex = bihleaf->itemindex;
11031                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11032                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11033                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11034                                 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);
11035                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11036                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11037                                 break;
11038                         case BIH_RENDERTRIANGLE:
11039                                 triangleindex = bihleaf->itemindex;
11040                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11041                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11042                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11043                                 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);
11044                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11045                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11046                                 break;
11047                         }
11048                 }
11049         }
11050
11051         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11052
11053         if (r_showtris.integer || (r_shownormals.value != 0))
11054         {
11055                 if (r_showdisabledepthtest.integer)
11056                 {
11057                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11058                         GL_DepthMask(false);
11059                 }
11060                 else
11061                 {
11062                         GL_BlendFunc(GL_ONE, GL_ZERO);
11063                         GL_DepthMask(true);
11064                 }
11065                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11066                 {
11067                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11068                                 continue;
11069                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11070                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11071                         {
11072                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11073                                 if (r_showtris.value > 0)
11074                                 {
11075                                         if (!rsurface.texture->currentlayers->depthmask)
11076                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11077                                         else if (ent == r_refdef.scene.worldentity)
11078                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11079                                         else
11080                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11081                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11082                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11083                                         RSurf_DrawBatch();
11084                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11085                                         CHECKGLERROR
11086                                 }
11087                                 if (r_shownormals.value < 0)
11088                                 {
11089                                         qglBegin(GL_LINES);
11090                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11091                                         {
11092                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11093                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11094                                                 qglVertex3f(v[0], v[1], v[2]);
11095                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11096                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11097                                                 qglVertex3f(v[0], v[1], v[2]);
11098                                         }
11099                                         qglEnd();
11100                                         CHECKGLERROR
11101                                 }
11102                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11103                                 {
11104                                         qglBegin(GL_LINES);
11105                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11106                                         {
11107                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11108                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11109                                                 qglVertex3f(v[0], v[1], v[2]);
11110                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11111                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11112                                                 qglVertex3f(v[0], v[1], v[2]);
11113                                         }
11114                                         qglEnd();
11115                                         CHECKGLERROR
11116                                         qglBegin(GL_LINES);
11117                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11118                                         {
11119                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11120                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11121                                                 qglVertex3f(v[0], v[1], v[2]);
11122                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11123                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11124                                                 qglVertex3f(v[0], v[1], v[2]);
11125                                         }
11126                                         qglEnd();
11127                                         CHECKGLERROR
11128                                         qglBegin(GL_LINES);
11129                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11130                                         {
11131                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11132                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11133                                                 qglVertex3f(v[0], v[1], v[2]);
11134                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11135                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11136                                                 qglVertex3f(v[0], v[1], v[2]);
11137                                         }
11138                                         qglEnd();
11139                                         CHECKGLERROR
11140                                 }
11141                         }
11142                 }
11143                 rsurface.texture = NULL;
11144         }
11145 }
11146
11147 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11148 int r_maxsurfacelist = 0;
11149 const msurface_t **r_surfacelist = NULL;
11150 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11151 {
11152         int i, j, endj, flagsmask;
11153         dp_model_t *model = r_refdef.scene.worldmodel;
11154         msurface_t *surfaces;
11155         unsigned char *update;
11156         int numsurfacelist = 0;
11157         if (model == NULL)
11158                 return;
11159
11160         if (r_maxsurfacelist < model->num_surfaces)
11161         {
11162                 r_maxsurfacelist = model->num_surfaces;
11163                 if (r_surfacelist)
11164                         Mem_Free((msurface_t**)r_surfacelist);
11165                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11166         }
11167
11168         RSurf_ActiveWorldEntity();
11169
11170         surfaces = model->data_surfaces;
11171         update = model->brushq1.lightmapupdateflags;
11172
11173         // update light styles on this submodel
11174         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11175         {
11176                 model_brush_lightstyleinfo_t *style;
11177                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11178                 {
11179                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11180                         {
11181                                 int *list = style->surfacelist;
11182                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11183                                 for (j = 0;j < style->numsurfaces;j++)
11184                                         update[list[j]] = true;
11185                         }
11186                 }
11187         }
11188
11189         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11190
11191         if (debug)
11192         {
11193                 R_DrawDebugModel();
11194                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11195                 return;
11196         }
11197
11198         rsurface.lightmaptexture = NULL;
11199         rsurface.deluxemaptexture = NULL;
11200         rsurface.uselightmaptexture = false;
11201         rsurface.texture = NULL;
11202         rsurface.rtlight = NULL;
11203         numsurfacelist = 0;
11204         // add visible surfaces to draw list
11205         for (i = 0;i < model->nummodelsurfaces;i++)
11206         {
11207                 j = model->sortedmodelsurfaces[i];
11208                 if (r_refdef.viewcache.world_surfacevisible[j])
11209                         r_surfacelist[numsurfacelist++] = surfaces + j;
11210         }
11211         // update lightmaps if needed
11212         if (model->brushq1.firstrender)
11213         {
11214                 model->brushq1.firstrender = false;
11215                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11216                         if (update[j])
11217                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11218         }
11219         else if (update)
11220         {
11221                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11222                         if (r_refdef.viewcache.world_surfacevisible[j])
11223                                 if (update[j])
11224                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11225         }
11226         // don't do anything if there were no surfaces
11227         if (!numsurfacelist)
11228         {
11229                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11230                 return;
11231         }
11232         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11233
11234         // add to stats if desired
11235         if (r_speeds.integer && !skysurfaces && !depthonly)
11236         {
11237                 r_refdef.stats.world_surfaces += numsurfacelist;
11238                 for (j = 0;j < numsurfacelist;j++)
11239                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11240         }
11241
11242         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11243 }
11244
11245 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11246 {
11247         int i, j, endj, flagsmask;
11248         dp_model_t *model = ent->model;
11249         msurface_t *surfaces;
11250         unsigned char *update;
11251         int numsurfacelist = 0;
11252         if (model == NULL)
11253                 return;
11254
11255         if (r_maxsurfacelist < model->num_surfaces)
11256         {
11257                 r_maxsurfacelist = model->num_surfaces;
11258                 if (r_surfacelist)
11259                         Mem_Free((msurface_t **)r_surfacelist);
11260                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11261         }
11262
11263         // if the model is static it doesn't matter what value we give for
11264         // wantnormals and wanttangents, so this logic uses only rules applicable
11265         // to a model, knowing that they are meaningless otherwise
11266         if (ent == r_refdef.scene.worldentity)
11267                 RSurf_ActiveWorldEntity();
11268         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11269                 RSurf_ActiveModelEntity(ent, false, false, false);
11270         else if (prepass)
11271                 RSurf_ActiveModelEntity(ent, true, true, true);
11272         else if (depthonly)
11273         {
11274                 switch (vid.renderpath)
11275                 {
11276                 case RENDERPATH_GL20:
11277                 case RENDERPATH_D3D9:
11278                 case RENDERPATH_D3D10:
11279                 case RENDERPATH_D3D11:
11280                 case RENDERPATH_SOFT:
11281                 case RENDERPATH_GLES2:
11282                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11283                         break;
11284                 case RENDERPATH_GL13:
11285                 case RENDERPATH_GL11:
11286                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11287                         break;
11288                 }
11289         }
11290         else
11291         {
11292                 switch (vid.renderpath)
11293                 {
11294                 case RENDERPATH_GL20:
11295                 case RENDERPATH_D3D9:
11296                 case RENDERPATH_D3D10:
11297                 case RENDERPATH_D3D11:
11298                 case RENDERPATH_SOFT:
11299                 case RENDERPATH_GLES2:
11300                         RSurf_ActiveModelEntity(ent, true, true, false);
11301                         break;
11302                 case RENDERPATH_GL13:
11303                 case RENDERPATH_GL11:
11304                         RSurf_ActiveModelEntity(ent, true, false, false);
11305                         break;
11306                 }
11307         }
11308
11309         surfaces = model->data_surfaces;
11310         update = model->brushq1.lightmapupdateflags;
11311
11312         // update light styles
11313         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11314         {
11315                 model_brush_lightstyleinfo_t *style;
11316                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11317                 {
11318                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11319                         {
11320                                 int *list = style->surfacelist;
11321                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11322                                 for (j = 0;j < style->numsurfaces;j++)
11323                                         update[list[j]] = true;
11324                         }
11325                 }
11326         }
11327
11328         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11329
11330         if (debug)
11331         {
11332                 R_DrawDebugModel();
11333                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11334                 return;
11335         }
11336
11337         rsurface.lightmaptexture = NULL;
11338         rsurface.deluxemaptexture = NULL;
11339         rsurface.uselightmaptexture = false;
11340         rsurface.texture = NULL;
11341         rsurface.rtlight = NULL;
11342         numsurfacelist = 0;
11343         // add visible surfaces to draw list
11344         for (i = 0;i < model->nummodelsurfaces;i++)
11345                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11346         // don't do anything if there were no surfaces
11347         if (!numsurfacelist)
11348         {
11349                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11350                 return;
11351         }
11352         // update lightmaps if needed
11353         if (update)
11354         {
11355                 int updated = 0;
11356                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11357                 {
11358                         if (update[j])
11359                         {
11360                                 updated++;
11361                                 R_BuildLightMap(ent, surfaces + j);
11362                         }
11363                 }
11364         }
11365         if (update)
11366                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11367                         if (update[j])
11368                                 R_BuildLightMap(ent, surfaces + j);
11369         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11370
11371         // add to stats if desired
11372         if (r_speeds.integer && !skysurfaces && !depthonly)
11373         {
11374                 r_refdef.stats.entities_surfaces += numsurfacelist;
11375                 for (j = 0;j < numsurfacelist;j++)
11376                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11377         }
11378
11379         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11380 }
11381
11382 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11383 {
11384         static texture_t texture;
11385         static msurface_t surface;
11386         const msurface_t *surfacelist = &surface;
11387
11388         // fake enough texture and surface state to render this geometry
11389
11390         texture.update_lastrenderframe = -1; // regenerate this texture
11391         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11392         texture.currentskinframe = skinframe;
11393         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11394         texture.offsetmapping = OFFSETMAPPING_OFF;
11395         texture.offsetscale = 1;
11396         texture.specularscalemod = 1;
11397         texture.specularpowermod = 1;
11398
11399         surface.texture = &texture;
11400         surface.num_triangles = numtriangles;
11401         surface.num_firsttriangle = firsttriangle;
11402         surface.num_vertices = numvertices;
11403         surface.num_firstvertex = firstvertex;
11404
11405         // now render it
11406         rsurface.texture = R_GetCurrentTexture(surface.texture);
11407         rsurface.lightmaptexture = NULL;
11408         rsurface.deluxemaptexture = NULL;
11409         rsurface.uselightmaptexture = false;
11410         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11411 }
11412
11413 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)
11414 {
11415         static msurface_t surface;
11416         const msurface_t *surfacelist = &surface;
11417
11418         // fake enough texture and surface state to render this geometry
11419         surface.texture = texture;
11420         surface.num_triangles = numtriangles;
11421         surface.num_firsttriangle = firsttriangle;
11422         surface.num_vertices = numvertices;
11423         surface.num_firstvertex = firstvertex;
11424
11425         // now render it
11426         rsurface.texture = R_GetCurrentTexture(surface.texture);
11427         rsurface.lightmaptexture = NULL;
11428         rsurface.deluxemaptexture = NULL;
11429         rsurface.uselightmaptexture = false;
11430         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11431 }